为什么in运算符对于未定义的属性返回true?

时间:2015-06-01 18:39:19

标签: javascript

描述

我总是错误地认为in运算符正在检查属性的undefined值。快速查看ES5 specification表明in运算符最终会调用[[GetProperty]],这将返回属性的值。

为什么将foo.bar设置为undefined时,in运算符返回true,而当foo.bar从未设置时falseundefined 1}},即使它们的值都为var foo = { bar: undefined }; 'baz' in foo // -> false 'bar' in foo // -> true

实施例

foo.bar

相关:typeof foo['bar'] !== 'undefined' vs. 'bar' in foo 相关问题询问何时undefined永远不会设置为{{1}}。

1 个答案:

答案 0 :(得分:3)

注意:在研究问题时我找到了答案,因为我已经花了时间,所以我决定发布我发现的内容。

他们返回不同值的原因是[[GetProperty]]调用[[GetOwnProperty]],这不会返回属性值。 [[GetOwnProperty]]返回一个Property Descriptor,它描述了属性是否可枚举,可写和它的值。

当您在问题中将undefined设置为bar时,会创建属性描述符*,[[Value]]undefined。当为[[GetOwnProperty]]调用bar时,将返回属性描述符,而使用baz时,将返回undefined。这意味着[[GetProperty]]会返回bar的已定义值,然后[[HasProperty]]返回true,而不是false。这反过来又使in运算符返回true

* 这是谎言,但为了简单起见。

规范跟踪

来自Annotated ECMAScript 5.1

注意:以下数字会尽可能链接到规范参考

对于:'bar' in foo

  • 1.评估'bar'会给出字符串'bar'
  • {li} 2. GetValue 'bar'将返回值'bar'
  • 3.评估foo会提供参考foo
  • 4. GetValue foo将返回'foo'的值,我们的对象
  • 5. Type的值foo是一个对象,没有异常抛出
    1. 'bar'
    2. toString返回字符串'bar,调用[[HasProperty]]
      • 1. [[GetProperty]]返回Property Descriptor(不是undefined
      • 1. [[GetOwnProperty]]返回属性描述符(不是undefined
        1. foo拥有名为bar的属性,不返回undefined
        1. 创建没有字段的属性描述符
        1. foo.bar
        2. 创建X.
        1. X是数据属性,因此将[[Value]]设置为undefined并设置[[Writable]]
        1. 跳过其他分支
        1. 设置[[可枚举]]
        1. 设置[[可配置]]
        1. 返回属性描述符
        1. 属性描述符未定义,返回属性描述符。
        1. 属性描述符不是undefined,因此不要返回false
        1. 其他,返回true