it-roy-ru.com

Нулевой безопасный доступ к собственности (и условное присвоение) в ES6/2015

Существует ли в ES6 оператор безопасного доступа к свойству null (нулевое распространение/существование), например?.in CoffeeScript ? Или это запланировано на ES7?

var aThing = getSomething()
...
aThing = possiblyNull?.thing

Это будет примерно так:

if (possiblyNull != null) aThing = possiblyNull.thing

В идеале решение не должно присваивать (даже undefined) aThing, если possiblyNull равно null

109
ııı

Выполняемая функция, которая в настоящее время находится на этапе 1: необязательное связывание.

https://github.com/tc39/proposal-optional-chaining

Если вы хотите использовать его сегодня, есть плагин Babel, который выполняет это.

https://github.com/davidyaha/ecmascript-optionals-proposal

Update (2017-08-01): Если вы хотите использовать официальный плагин, вы можете попробовать альфа-сборку Babel 7 с новым преобразованием. Ваш пробег может отличаться

https://www.npmjs.com/package/babel-plugin-transform-optional-chaining

72
basicdays

Это не так хорошо, как? оператор, но для достижения аналогичного результата вы могли бы сделать:

user && user.address && user.address.postcode

Поскольку null и undefined являются значениями falsy ( см. Эту ссылку ), свойство после оператора && доступно только в том случае, если прецедент не равен нулю или не определен.

В качестве альтернативы вы можете написать такую ​​функцию:

function _try(func, fallbackValue) {
    try {
        var value = func();
        return (value === null || value === undefined) ? fallbackValue : value;
    } catch (e) {
        return fallbackValue;
    }
}

Использование:

_try(() => user.address.postcode) // return postcode or undefined 

Или с запасным значением:

_try(() => user.address.postcode, "none") // return postcode or a custom string
41
tocqueville

Нет. Вы можете использовать lodash # get или что-то подобное для этого в JavaScript.

28
Girafa

Альтернатива ванили для безопасного доступа к собственности

(((a.b || {}).c || {}).d || {}).e

Наиболее кратким условным заданием, вероятно, будет

try { b = a.b.c.d.e } catch(e) {}
10
yagger

Судя по списку здесь , в настоящее время нет предложений по добавлению безопасного обхода в Ecmascript. Так что не только нет приятного способа сделать это, но он не будет добавлен в обозримом будущем.

3
Antimony

Я знаю, что это вопрос JavaScript, но я думаю, что Ruby справляется с этим всеми запрошенными способами, поэтому я думаю, что это актуальная точка отсчета. 

.&, try и && имеют свои сильные стороны и потенциальные подводные камни. Здесь вы найдете множество вариантов: http://mitrev.net/Ruby/2015/11/13/the-operator-in-Ruby/

TLDR; Вывод Rubyists заключается в том, что Dig проще для глаз и является более надежной гарантией того, что значение или null будет присвоено.

Вот простая реализация в TypeScript:

export function Dig(target: any, ...keys: Array<string>): any {
  let digged = target
  for (const key of keys) {
    if (typeof digged === 'undefined') {
      return undefined // can also return null or a default value
    }
    if (typeof key === 'function') {
      digged = key(digged)
    } else {
      digged = digged[key]
    }
  }
  return digged
}

Это может быть использовано для любой глубины вложенности и функций функций.

a = Dig(b, 'c', 'd', 'e');
foo = () => ({});
bar = Dig(a, foo, 'b', 'c')

Подход try одинаково хорош для чтения в JS, как показано в предыдущих ответах. Это также не требует зацикливания, что является одним из недостатков этой реализации. 

0
theUtherSide

Безопасный метод глубокого получения выглядит как естественная подгонка для underscore.js, но здесь проблема состоит в том, чтобы избегать строкового программирования. Измените ответ @ Felipe, чтобы избежать программирования строк (или, по крайней мере, отодвинуть Edge case обратно к вызывающей стороне):

function safeGet(obj, props) {
   return (props.length==1) ? obj[keys[0]] :safeGet(obj[props[0]], props.slice(1))
}

Пример: 

var test = { 
  a: { 
    b: 'b property value',
    c: { }
  } 
}
safeGet(test, ['a', 'b']) 
safeGet(test, "a.b".split('.'))  
0
prototype