如何使用CoffeeScript存在运算符检查未定义的某些对象属性?

Prz*_*mek 26 coffeescript existential-operator

我想使用CoffeeScript存在运算符来检查undefined的一些对象属性.但是,我遇到了一个小问题.

像这样的代码:

console.log test if test?
Run Code Online (Sandbox Code Playgroud)

编译为:

if (typeof test !== "undefined" && test !== null) console.log(test);
Run Code Online (Sandbox Code Playgroud)

这是我希望看到的行为.但是,当我尝试将它用于对象属性时,如下所示:

console.log test.test if test.test?
Run Code Online (Sandbox Code Playgroud)

我得到类似的东西:

if (test.test != null) console.log(test.test);
Run Code Online (Sandbox Code Playgroud)

哪个看起来不像是对未定义的检查.我可以实现与使用对象相同(1:1)行为的唯一方法是使用更大的检查:

console.log test.test if typeof test.test != "undefined" and test.test != null
Run Code Online (Sandbox Code Playgroud)

问题是 - 我做错了吗?或者编译后的代码是否足以检查属性是否存在(带有类型转换的空检查)?

Tre*_*ham 52

这是与存在运算符混淆的常见点:有时候

x?
Run Code Online (Sandbox Code Playgroud)

编译成

typeof test !== "undefined" && test !== null
Run Code Online (Sandbox Code Playgroud)

和其他时候它只是编译

x != null
Run Code Online (Sandbox Code Playgroud)

这两个是等价的,因为x != nullfalse时,x要么是nullundefined.这x != null是一种更紧凑的表达方式(x !== undefined && x !== null).typeof编译发生的原因是编译器认为x可能根本没有定义,在这种情况下,执行相等性测试会触发ReferenceError: x is not defined.

在您的特定情况下,test.test可能具有该值undefined,但您无法ReferenceError通过引用现有对象上的未定义属性来获取,因此编译器会选择较短的输出.


mu *_*ort 20

这个JavaScript:

a.foo != null
Run Code Online (Sandbox Code Playgroud)

实际上确实检查foo属性a是否也不undefinednull.请注意,它a.foo?被转换为使用!= null而不是使用的JavaScript !== null.转换!=确实意味着这两个都是真的:

null == null
undefined == null
Run Code Online (Sandbox Code Playgroud)

简单a?成为这个JavaScript:

typeof a !== "undefined" && a !== null
Run Code Online (Sandbox Code Playgroud)

因为有三个条件需要检查:

  1. a在任何地方都有范围吗?
  2. 是否a有一个值undefined
  3. 是否a有一个值null

第一个条件很重要,因为a != null如果a范围内没有,但说typeof a === 'undefined'不会触发ReferenceError .该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)
Run Code Online (Sandbox Code Playgroud)

但是,if(a.foo)if(a.foo?)在他们如何处理不同0,false''.