JavaScript表达式[1 [{}]]究竟是如何解析的?

Mat*_*hen 6 javascript parsing literals

你能解释一下JavaScript表达式:

[1 [{}]]
Run Code Online (Sandbox Code Playgroud)

分析/求值?在Firefox,Chrome,Konqueror和rhino中,它似乎创建了一个包含单个元素的数组undefined.但是,我不明白为什么.

在Firefox中:

[1 [{}]].toSource()
Run Code Online (Sandbox Code Playgroud)

产生

[(void 0)]
Run Code Online (Sandbox Code Playgroud)

用其他JavaScript值替换1似乎产生相同的结果.

更新:我想我现在明白了.codeka,Adrian和CMS澄清了一些事情.至于标准,我试图通过ECMAScript 5.

  1. 1 [{}] 是一个属性访问器,因此它在第11.2.1节中介绍.
  2. baseReference是评估的结果1,所以仍然1.
  3. baseValue = GetValue(baseReference) == 1.
  4. GetValue(§8.7.1),Type(1)不是Reference(已解析的名称绑定),因此返回1.
  5. propertyNameReference是评估的结果{},所以是一个空对象.
  6. propertyNameValue = GetValue(propertyNameReference) == {}
  7. CheckObjectCoercible(baseValue)(§9.10),我们返回(Number是对象可强制的).
  8. propertyNameString = ToString(propertyNameValue)
  9. ToString(§9.8),返回ToString(ToPrimitive({}, hint String))
  10. ToPrimitive(§9.1),返回对象的结果[[DefaultValue]],传递PreferredType(字符串).
  11. [[DefaultValue]](§8.12.8)中,让toString成为[[Get]]带参数的结果toString.
  12. 这在§15.2.4.2中定义为返回"[object " + [[Class]] + "]",其中[[Class]]是默认对象原型的"Object".
  13. 既然有可调用的toString,我们有说法称它this{}.
  14. 返回type的值Reference,其基值为BaseValue(1),其引用的名称为propertyNameString("[object Object]").

然后我们转到Array初始化器(第11.1.4节),并用结果构造一个单元素数组.

CMS*_*CMS 15

阅读OP和尼克的评论,我想我可以更多地扩展阿德里安的答案,使其更清晰.

这是完全有效的JavaScript.

JavaScript将对象属性名称作为字符串处理,对象不能包含其他类型或其他对象作为,它们只是字符串.

括号表示法属性accessor(MemberExpression [ Expression ])隐式将括号中的表达式转换为字符串,因此:

var obj = {};
obj[{}] = "foo";
alert(obj["[object Object]"]); // foo
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,您可以看到我为{}属性赋值,并且{}.toString()(或{}+'')生成字符串"[object Object](via Object.prototype.toString).

该表达式1 [{}]隐式地将1 Number原语转换为对象(这是由属性访问器创建的),并且它查找名为"[object Object]"属性查找的属性,Number.prototype并在Object.prototype对象上进行,例如:

1['toString'] === Number.prototype.toString; // true
Run Code Online (Sandbox Code Playgroud)

最后,1 [{}]表达式本身用括号([1 [{}]])括起来,这实际上是一个数组文字.

总之,解析器如何评估表达式:

 [1 [{}]];
 //   ^ The accessor expression is evaluated and converted to string

 [1 ["[object Object]"]];
 // ^ A property lookup is made on an Number object 
 //   trying to access a property named "[object Object]"

 [undefined];
 //   ^ the property is obviously not found

   [undefined];
 //^         ^
 // An array literal is created with an element `0` which its value is `undefined`
Run Code Online (Sandbox Code Playgroud)


Adr*_*ian 8

这是因为您正在尝试获取{}对象的属性,1然后将其放在数组中.1不具有这样的性质{},所以1[{}]undefined.

如果1用数组替换它,您将看到它是如何工作的.随着1作为[5]{}作为0,它是[[5][0]].

另外,请记住,它obj['property']是一样的obj.property.


Dea*_*ing 7

如果我们分解一下,你会看到:

var foo = 1;
var bar = {};
var baz = foo[bar];

[baz];
Run Code Online (Sandbox Code Playgroud)

我相信它是有效的JavaScript,但我不是专家......

  • @Matthew:我的猜测是因为`1 [{}]`是未定义的,`(void 0)`只是解释器用于表示"未定义"的"规范"形式. (2认同)