Как использовать экзистенциальный оператор CoffeeScript для проверки некоторых свойств объекта для undefined?
Я хотел бы использовать экзистенциальный оператор CoffeeScript для проверки некоторых свойств объекта для undefined. Однако я столкнулся с небольшой проблемой.
Код вроде этого:
console.log test if test?
Скомпилируется:
if (typeof test !== "undefined" && test !== null) console.log(test);
Какое поведение я бы хотел видеть. Однако, когда я пытаюсь использовать его против свойств объекта, например:
console.log test.test if test.test?
Я получаю что-то вроде этого:
if (test.test != null) console.log(test.test);
Что не похоже на проверку против undefined вообще. Единственный способ, которым я мог достичь такого же (1:1) поведения, как использование его для объектов, - это сделать большую проверку:
console.log test.test if typeof test.test != "undefined" and test.test != null
Вопрос: я делаю что-то неправильно? Или это скомпилированный код, который достаточно для проверки существования свойства (нулевая проверка с преобразованием типов)?
Ответы
Ответ 1
Это общая точка смущения с экзистенциальным оператором: Иногда
x?
компилируется в
typeof test !== "undefined" && test !== null
и в других случаях он просто компилируется в
x != null
Оба эквивалентны, потому что x != null
будет false
, когда x
либо null
, либо undefined
. Итак, x != null
- более компактный способ выражения (x !== undefined && x !== null)
. Причина компиляции typeof
заключается в том, что компилятор считает, что x
может вообще не определяться, и в этом случае выполнение теста равенства вызовет ReferenceError: x is not defined
.
В вашем конкретном случае test.test
может иметь значение undefined
, но вы не можете получить ReferenceError
, ссылаясь на свойство undefined на существующий объект, поэтому компилятор выбирает более короткий вывод.
Ответ 2
Этот JavaScript:
a.foo != null
действительно проверяет, не является ли свойство foo
a
ни undefined
, ни null
. Обратите внимание, что a.foo?
переводится на JavaScript, который использует != null
, а не !== null
. Преобразования, которые !=
означают, что оба они верны:
null == null
undefined == null
Простой a?
становится этим JavaScript:
typeof a !== "undefined" && a !== null
потому что есть три условия для проверки:
- Есть ли
a
в области видимости в любом месте?
- Имеет ли значение
a
значение undefined
?
- Имеет ли
a
значение null
?
Первое условие важно, так как просто говоря a != null
будет запускать ReferenceError, если в области нет a
, но typeof a === 'undefined'
не будет. Проверка typeof
также выполняет условие a === undefined
в 2. Затем мы можем завершить его строгим тестом a !== null
, поскольку он заботится о 3 без снижения производительности ненужного !=
(примечание: !=
и ==
медленнее, чем !==
и ===
из-за неявных преобразований).
Небольшое чтение о том, что !=
и !==
может быть плодотворным:
MDN: Операторы сравнения
Что касается вашего комментария к удаленному ответу, if(a.foo)
является вполне допустимым синтаксисом , если вы заполняете оператор if
:
if(a.foo)
do_interesting_things()
# or
do_interesting_things() if(a.foo)
Однако if(a.foo)
и if(a.foo?)
отличаются тем, как они обрабатывают 0
, false
и ''
.
Ответ 3
Дикая догадка; вы пробовали console.log test.test if test?.test?
?
Просто протестируйте его с помощью coffee -p -e 'console.log test.test if test?.test?'
, который компилируется в:
(function() {
if ((typeof test! == "undefined" && test! == null? test.test: void 0)!= Null) { console.log(test.test); }
}) вызова (это);.