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

JavaScript表达式[1[{}]]到底是如何解析的?,javascript,parsing,literals,Javascript,Parsing,Literals,您能否解释一下JavaScript表达式是如何: [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

您能否解释一下JavaScript表达式是如何:

[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`
解析/计算?在Firefox、Chrome、Konqueror和rhino中,它似乎创建了一个包含单个元素的数组,
undefined
。然而,我不明白为什么

在Firefox中:

[1 [{}]].toSource()
产生

[(void 0)]
用其他JavaScript值替换1似乎会产生相同的结果

更新:我想我现在明白了。科德卡、阿德里安和CMS澄清了事情。就标准而言,我尝试遍历ECMAScript 5

  • 1[{}]
    是一个属性访问器,因此在§11.2.1中有介绍
  • baseReference
    是计算
    1
    的结果,因此仍然是
    1
  • baseValue=GetValue(baseReference)==1
  • GetValue
    (§8.7.1),
    类型(1)
    不是
    参考(解析名称绑定),因此返回1
  • propertyNameReference
    是计算
    {}
    的结果,因此为空对象
  • propertyNameValue=GetValue(propertyNameReference)=={}
  • checkObjectImprovalible(baseValue)
    (§9.10)中,我们返回(数字是对象可强制的)
  • propertyNameString=ToString(propertyNameValue)
  • ToString
    (§9.8)中,返回
    ToString(ToPrimitive({},hint String))
  • ToPrimitive
    (§9.1)中,返回对象的
    [[DefaultValue]]]
    ,传递
    首选类型
    (字符串)
  • [[DefaultValue]]
    (§8.12.8)中,让toString是带有参数
    toString
    [[Get]]]
    的结果
  • 这在§15.2.4.2中定义为返回
    “[object”+[[Class]]+“]”
    ,其中
    [[Class]]
    是默认对象原型的“object”
  • 由于有一个可调用的
    toString
    ,我们用参数
    将其称为this
    {}
  • 返回类型为
    Reference
    的值,其基值为
    BaseValue
    (1),引用的名称为
    propertyNameString
    “[对象对象]”

  • 然后我们转到数组初始值设定项(§11.1.4),并用结果构造一个单元素数组。

    如果我们稍微分解一下,您将看到:

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

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

    这是因为您试图获取对象
    1
    的属性
    {}
    ,然后将其放入数组中
    1
    没有属性
    {}
    ,因此
    1[{}]
    未定义的

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

    另外,请记住,
    obj['property']
    obj.property

    阅读本文时,我想我可以进一步展开,使其更清晰

    它是完全有效的JavaScript

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

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

    var obj = {};
    obj[{}] = "foo";
    alert(obj["[object Object]"]); // foo
    
    在上面的示例中,您可以看到我为
    {}
    属性赋值,并且
    {}.toString()
    (或
    {}+'
    )生成字符串
    “[object object]
    (via)

    表达式
    1[{}]
    隐式地将1
    Number
    原语转换为对象(由属性访问器生成),并查找名为
    “[object object]”的属性。
    Number.prototype
    对象进行属性查找。例如,prototype
    对象:

    1['toString'] === Number.prototype.toString; // true
    
    最后,
    1[{}]
    表达式本身被括在括号中(
    [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`
    

    我不确定为什么这会是有效的JavaScript…所以引擎尝试处理它时会得到不可预测的结果…我觉得状态正常。@Nick,我也怀疑它是否是有效的JS,我愿意接受它只是未定义行为的可能性。然而,事实上,所有4个引擎(都有单独的实现)用同样的方式解析它至少很有趣。@Matthew-Adrian的回答很好地解释了这4种浏览器的行为,我仍然不认为
    [object]
    是一个有效的访问器,但…所以它如何处理这个问题仍然取决于每个引擎。虽然这是一个边缘问题,但我在3.1规范中找不到任何说明应该如何正确处理它的内容。@Nick,它似乎至少对ECMAScript 5有效。我试着在上面介绍它。@Nick:
    [对象]
    是有效的,但是
    对象将被转换为字符串。我想你已经看到了。我可能没有看到这一点,因为使用数字作为JavaScript对象是不寻常的,而空对象是不寻常的键。你对
    [(void 0)]
    部分有什么想法吗?@Matthew:我猜是因为
    1[{}]
    是未定义的,
    (void 0)
    只是解释程序表示“未定义”的“规范”形式。