简体   繁体   English

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

[英]Why does the in operator return true for a property that is undefined?

Description 描述

I always wrongly assumed that the in operator was checking for an undefined value for the property. 我总是错误地认为in运算符正在检查属性的undefined值。 A quick look at the ES5 specification shows that the in operator eventually calls [[GetProperty]] , which would return the value of the property. 快速浏览ES5规范会显示in运算符最终调用[[GetProperty]] ,它将返回属性的值。

Why is it that the when foo.bar is set to undefined the in operator returns true , while when foo.bar is never set it is false , even though they both have a value of undefined ? 为什么当foo.bar被设置为undefinedin运算符返回true ,而当foo.bar从未设置为false ,即使它们都具有undefined值?

Example

var foo = {
    bar: undefined
};

'baz' in foo
// -> false

'bar' in foo
// -> true

Related: typeof foo['bar'] !== 'undefined' vs. 'bar' in foo The related questions was asking about when foo.bar is never set to undefined . 相关: typeof foo ['bar']!=='undefined'与foo中'bar'相关的问题是询问foo.bar永远不会设置为undefined

Note: While researching the question I found the answer, since I have already spent the time, I decided to post what I found. 注意:在研究问题时我找到了答案,因为我已经花了时间,所以我决定发布我发现的内容。


The reason why they return a different value is that [[GetProperty]] calls [[GetOwnProperty]] , which does does not return the property value. 它们返回不同值的原因是[[GetProperty]]调用[[GetOwnProperty]] ,它不会返回属性值。 [[GetOwnProperty]] returns a Property Descriptor which describes things like if the property is enumerable, writable and it's value. [[GetOwnProperty]]返回一个属性描述符 ,描述属性是否可枚举,可写和它的值。

When you set a property to undefined as with bar in the question, a Property Descriptor is created* with a [[Value]] of undefined . 当您在问题中使用bar设置属性为undefined ,将创建一个属性描述符*,其中[[Value]]undefined When [[GetOwnProperty]] is called for bar the Property Descriptor is returned, while with baz , undefined is returned. 当为bar调用[[GetOwnProperty]]时,返回属性描述符,而使用baz ,返回undefined This means that [[GetProperty]] return a defined value for bar , which then makes [[HasProperty]] return true , instead of false . 这意味着[[GetProperty]]返回bar的定义值,然后使[[HasProperty]]返回true ,而不是false Which in turn makes the in operator return true as well. 这反过来又使in运算符返回true

* this is a lie, but for simplicity sake. * 这是谎言,但为了简单起见。

Specification Trace 规范跟踪

From Annotated ECMAScript 5.1 . 来自Annotated ECMAScript 5.1

Note: Numbers below link to Spec reference where possible 注意:下面的数字会尽可能链接到Spec参考

For: 'bar' in foo 对于: 'bar' in foo

  • 1. Evaluating 'bar' gives a string 'bar' 1.评估'bar'给出了一个字符串'bar'
  • 2. GetValue of 'bar' will return the value 'bar' 2. GetValue'bar'将返回值'bar'
  • 3. Evaluating foo gives a reference foo 3.评价foo给出了一个参考foo
  • 4. GetValue of foo will return the value of 'foo' , our object 4. foo GetValue将返回'foo'的值,即我们的对象
  • 5. Type of value of foo is an object, no exception thrown 5. foo的值Type是一个对象,没有抛出异常
    1. toString of value of 'bar' returns the string 'bar , call [[HasProperty]] 值为'bar' toString返回字符串'bar ,调用[[HasProperty]]
      • 1. [[GetProperty]] returns Property Descriptor (not undefined ) 1. [[GetProperty]]返回属性描述符undefined
      • 1. [[GetOwnProperty]] return Property Descriptor (not undefined ) 1. [[GetOwnProperty]]返回属性描述符( undefined
        1. foo does have own property called bar , do not return undefined foo确实有自己的属性叫做bar ,不要返回undefined
        1. Create a Property Descriptor with no fields 创建没有字段的属性描述符
        1. Create X from foo.bar foo.bar创建X.
        1. X is a data property, so set [[Value]] to undefined and set [[Writable]] X是数据属性,因此将[[Value]]设置为undefined并设置[[Writable]]
        1. Else branch skipped 跳过其他分支
        1. Set [[Enumerable]] 设置[[可枚举]]
        1. Set [[Configurable]] 设置[[可配置]]
        1. Return Property Descriptor 返回属性描述符
        1. Property Descriptor is not undefined, return the Property Descriptor. 属性描述符未定义,返回属性描述符。
        1. Property Descriptor is not undefined , so don't return false 属性描述符undefined ,因此不要返回false
        1. else, return true 否则,返回true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM