Есть ли в javascript оператор с нулевым слиянием (Elvis) или оператор безопасной навигации? - PullRequest
173 голосов
/ 07 июля 2011

Я объясню на примере:

Оператор Элвиса (?:)

«Оператор Элвиса» - это сокращение троичного оператора Java.Один из примеров того, где это удобно, - это возвращение «разумного значения по умолчанию», если выражение принимает значение false или ноль.Простой пример может выглядеть так:

def gender = user.male ? "male" : "female"  //traditional ternary operator usage

def displayName = user.name ?: "Anonymous"  //more compact Elvis operator

Оператор безопасной навигации (?.)

Оператор безопасной навигации используется, чтобы избежать исключения NullPointerException.Обычно, когда у вас есть ссылка на объект, вам может потребоваться проверить, что он не является нулевым, прежде чем получить доступ к методам или свойствам объекта.Чтобы избежать этого, оператор безопасной навигации будет просто возвращать ноль вместо выдачи исключения, например:

def user = User.find( "admin" )           //this might be null if 'admin' does not exist
def streetName = user?.address?.street    //streetName will be null if user or user.address is null - no NPE thrown

Ответы [ 17 ]

123 голосов
/ 07 июля 2011

Вместо оператора Элвиса можно использовать логический оператор «ИЛИ»:

Например displayname = user.name || "Anonymous".

Но Javascript в настоящее время не имеет других функций. Я бы порекомендовал посмотреть CoffeeScript , если вам нужен альтернативный синтаксис. Он имеет некоторые сокращения, которые похожи на то, что вы ищете.

Например, экзистенциальный оператор

zip = lottery.drawWinner?().address?.zipcode

Функциональные клавиши

()->  // equivalent to function(){}

Сексуальный вызов функции

func 'arg1','arg2' // equivalent to func('arg1','arg2')

Есть также многострочные комментарии и классы. Очевидно, что вы должны скомпилировать это в javascript или вставить на страницу как <script type='text/coffeescript>', но это добавляет много функциональности :). Использование <script type='text/coffeescript'> действительно предназначено только для разработки, а не для производства.

90 голосов
/ 04 сентября 2015

Я думаю, что следующее эквивалентно оператору безопасной навигации, хотя и немного дольше:

var streetName = user && user.address && user.address.street;

streetName будет либо значением user.address.street, либо undefined.

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

var streetName = (user && user.address && user.address.street) || "Unknown Street";
79 голосов
/ 07 июля 2011

Javascript логический оператор ИЛИ имеет значение короткое замыкание и может заменить ваш оператор "Elvis":

var displayName = user.name || "Anonymous";

Однако, насколько мне известно, нет эквивалента вашему ?. оператору.

54 голосов
/ 17 июня 2016

Иногда я находил следующую идиому полезной:

a?.b.?c

можно переписать так:

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

Это использует тот факт, что получение неизвестных атрибутов объекта возвращаетundefined вместо того, чтобы генерировать исключение, как это происходит в null или undefined, поэтому мы заменяем null и undefined пустым объектом перед навигацией.

22 голосов
/ 16 января 2016

я думаю, что lodash _.get() может помочь здесь, как в _.get(user, 'name'), и более сложных задачах, таких как _.get(o, 'a[0].b.c', 'default-value')

13 голосов
/ 16 января 2018

Еще нет.Может быть, скоро.В настоящее время существует черновая спецификация:

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

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

На данный момент мне нравится использовать lodash get(object, path [,defaultValue])или дл delve(obj, keypath)

11 голосов
/ 07 июля 2011

Для первого вы можете использовать ||. Оператор Javascript «логический или», а не просто возвращает постоянные истинные и ложные значения, следует правилу возврата левого аргумента, если он истинен, и в противном случае оценивает и возвращает свой правый аргумент. Когда вас интересует только значение истинности, оно работает так же, но это также означает, что foo || bar || baz возвращает крайний левый из foo, bar или baz, который содержит истинное значение .

Вы не найдете такой, которая может отличить ложь от нуля, хотя 0 и пустая строка являются ложными значениями, поэтому избегайте использования конструкции value || default, где value может законно быть 0 или "".

5 голосов
/ 15 июля 2015

Вот простой эквивалент оператора Элвиса:

function elvis(object, path) {
    return path ? path.split('.').reduce(function (nestedObject, key) {
        return nestedObject && nestedObject[key];
    }, object) : object;
}

> var o = { a: { b: 2 }, c: 3 };
> elvis(o)

{ a: { b: 2 }, c: 3 }

> elvis(o, 'a');

{ b: 2 }

> elvis(o, 'a.b');

2

> elvis(o, 'x');

undefined
5 голосов
/ 07 июля 2011

Это более широко известен как оператор с нулевым слиянием.У Javascript его нет.

3 голосов
/ 07 июля 2011

Примерно такой же эффект можно получить, сказав:

var displayName = user.name || "Anonymous";
...