Доступ к нулевым свойствам (и условное назначение) в ES6/2015
Существует ли в SO6 (ES2015/JavaScript.next/Harmony) доступ к свойству (t20 > -safe) доступа к свойствам (нулевое распространение/существование), например ?.
в CoffeeScript например? Или это запланировано для ES7?
var aThing = getSomething()
...
aThing = possiblyNull?.thing
Это будет примерно так:
if (possiblyNull != null) aThing = possiblyNull.thing
В идеале решение не должно присваивать (даже undefined
) значение aThing
, если possiblyNull
равно null
Ответы
Ответ 1
Обновление (2019-06-27): кажется, что люди все еще находят это, вот текущая история:
Обновление (2017-08-01): Если вы хотите использовать официальный плагин, вы можете попробовать альфа-сборку Babel 7 с новым преобразованием. Ваш пробег может отличаться
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Оригинал:
Достигается функция, которая в настоящее время находится на этапе 1: необязательная цепочка.
https://github.com/tc39/proposal-optional-chaining
Если вы хотите использовать его сегодня, есть плагин Babel, который выполняет это.
https://github.com/davidyaha/ecmascript-optionals-proposal
Ответ 2
Это не так хорошо, как? оператор, но для достижения аналогичного результата вы могли бы сделать:
user && user.address && user.address.postcode
Поскольку null
и undefined
являются ложными значениями (см. Эту ссылку), свойство после оператора &&
доступно только в том случае, если в прецеденте оно не равно null или undefined.
В качестве альтернативы вы можете написать такую функцию:
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
Ответ 3
Нет. Вы можете использовать lodash # get или что-то в этом роде для JavaScript.
Ответ 4
Альтернатива Vanilla для безопасного доступа к ресурсам
(((a.b || {}).c || {}).d || {}).e
Наиболее сжатым условным назначением, вероятно, будет это
try { b = a.b.c.d.e } catch(e) {}
Ответ 5
Нет, в ES6 нет оператора распространения пустоты. Вам нужно будет пойти с одним из известных шаблонов.
Возможно, вы можете использовать деструктурирование:
({thing: aThing} = possiblyNull);
Существует много дискуссий (например, this), чтобы добавить такой оператор в ES7, но никто не снял.
Ответ 6
Переходя по списку здесь, в настоящее время нет предложения по добавлению безопасного обхода в Ecmascript. Таким образом, не только нет хорошего способа сделать это, но он не будет добавлен в обозримом будущем.
Ответ 7
Безопасный метод глубокого получения выглядит как естественная подгонка для underscore.js, но здесь проблема состоит в том, чтобы избегать строкового программирования. Модифицируйте ответ @Felipe, чтобы избежать программирования строки (или, по крайней мере, отодвинуть крайние случаи назад к вызывающей стороне):
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('.'))
Ответ 8
Я знаю, что это вопрос JavaScript, но я думаю, что Ruby справляется с этим всеми запрошенными способами, поэтому я считаю его уместным ориентиром.
.&
, try
, и && имеют свои сильные стороны и потенциальные подводные камни. Здесь вы найдете множество вариантов: http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/
TL;DR; Вывод 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, как показано в предыдущих ответах. Это также не требует зацикливания, что является одним из недостатков этой реализации.
Ответ 9
Я думал, что этот вопрос нуждается в небольшом обновлении для 2018. Это можно сделать без каких-либо библиотек, использующих Object.defineProperty()
и его можно использовать следующим образом:
myVariable.safeGet('propA.propB.propC');
Я считаю это безопасным (и js-этическим) из-за доступных для writeable
и enumerable
определений, теперь доступных для метода defineProperty
Object
, как документировано в MDN
определение функции ниже:
Object.defineProperty(Object.prototype, 'safeGet', {
enumerable: false,
writable: false,
value: function(p) {
return p.split('.').reduce((acc, k) => {
if (acc && k in acc) return acc[k];
return undefined;
}, this);
}
});
Я собрал jsBin с консольным выводом, чтобы продемонстрировать это. Обратите внимание, что в версии jsBin я также добавил пользовательское исключение для пустых значений. Это необязательно, и поэтому я оставил это из минимального определения выше.
Улучшения приветствуются