给出这四个定义对象然后尝试立即访问其属性的示例:
{foo: 'bar'}.foo
// syntax error: unexpected_token
我希望这会返回'foo'的值,但会导致语法错误。
我能想到的唯一解释是对象定义尚未执行,因此还不是对象。因此,似乎忽略了对象定义,并且语法错误来自于尝试执行:
.foo
// results in the same syntax error: unexpected_token
类似地:
{foo: 'bar'}['foo']
// returns the new Array ['foo']
这似乎证明了对象文字被忽略并且执行了尾随代码。
然而,这些工作正常:
({foo: 'bar'}).foo
// 'bar'
({foo: 'bar'})['foo']
// 'bar'
括号用于运行代码行,由于该括号运算符的结果是实例化对象,因此可以访问属性。
那么,为什么忽略对象定义而不立即执行?
答案 0 :(得分:8)
它没有被忽略,它只是不被认为是一个对象。
语句开头的 { ... }
被解析为Block[spec]代码。
如果是{foo: 'bar'}.foo
,则内部代码foo: "bar"
会被解析为LabelledStatement[spec]。
因此{foo: 'bar'}
正确解析(即使它没有按预期执行)但属性访问语法实际上导致语法错误,因为访问块上的属性无效。
正如您所注意到的那样,解决方案是将对象括在括号中:
({foo: 'bar'}).foo
使用(
启动语句会导致解析器在括号内搜索表达式。解析为表达式时{foo: 'bar'}
是Object Initializer[spec],正如您所期望的那样。
对于{foo: 'bar'}['foo']
,它实际上被解析为两个单独的语句:一个块({foo: 'bar'}
和一个数组初始值设定项(['foo']
):
{foo: 'bar'};
['foo'];
答案 1 :(得分:6)
这是“上下文”的问题,前两个例子不是对象文字!
它们是语句块,例如:
{ foo: 'bar' }
以上代码被评估为一个块,其中包含指向表达式语句(字符串文字foo
)的labelled statement('bar'
)。
当您将它包装在括号上时,代码将在表达式上下文中进行评估,因此语法与Object Literal语法匹配。
实际上还有其他方法可以强制进行表达式求值,当你直接应用于对象文字时,你会发现 dot 属性访问符号有效。例如:
({foo:'bar'}.foo); // 'bar'
0, {foo:'bar'}.foo; // 'bar'
0||{foo:'bar'}.foo; // 'bar'
1&&{foo:'bar'}.foo; // 'bar'
// etc...
现在在你的第二个例子中:
{foo: 'bar'}['foo']
这里发生的是评估两个语句,首先是块,然后是包含Array文字的表达式语句。
语法歧义是否与函数表达式与函数声明相似。
另见: