我想使用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);
哪个看起来不像是对未定义的检查。我可以实现与使用对象相同(1:1)行为的唯一方法是使用更大的检查:
console.log test.test if typeof test.test != "undefined" and test.test != null
问题是 - 我做错了吗?或者编译后的代码是否足以检查是否存在属性(带有类型转换的空检查)?
答案 0 :(得分:50)
这是与存在主体运算符混淆的常见点:有时候
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
,但您无法通过引用现有对象上的未定义属性来获取{{1}},因此编译器选择较短的输出。
答案 1 :(得分:20)
这个JavaScript:
a.foo != null
实际上会检查foo
的{{1}}属性是a
还是undefined
。请注意,null
已转换为使用a.foo?
而不是!= null
的JavaScript。 !== null
所做的转换意味着这两者都是正确的:
!=
普通null == null
undefined == null
成为这个JavaScript:
a?
因为有三个条件需要检查:
typeof a !== "undefined" && a !== null
?a
的值是否为a
?undefined
的值是否为a
?第一个条件非常重要,因为如果范围中没有null
但是a != null
不会,a
会触发ReferenceError。 typeof a === 'undefined'
检查还会处理 2 中的typeof
条件。然后我们可以通过严格的a === undefined
测试来完成它,因为它可以处理 3 而不会对不必要的a !== null
造成性能损失(注意:!=
和{由于隐式转换,{1}}慢于!=
和==
。
关于!==
和===
做什么可能会有所收获:
就您对已删除答案的评论而言,!=
是完全有效的语法如果您完成!==
语句:
if(a.foo)
但是,if
和if(a.foo)
do_interesting_things()
# or
do_interesting_things() if(a.foo)
处理if(a.foo)
,if(a.foo?)
和0
的方式不同。
答案 2 :(得分:4)
疯狂猜测;你试过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); }
})调用(这);