立即访问对象的属性

wlm*_*rer 4 javascript

给出这四个定义对象然后尝试立即访问其属性的示例:

{foo: 'bar'}.foo
// syntax error: unexpected_token
Run Code Online (Sandbox Code Playgroud)

我希望这会返回'foo'的值,但会导致语法错误.

我能想到的唯一解释是对象定义尚未执行,因此还不是对象.因此,似乎忽略了对象定义,并且语法错误来自于尝试执行:

.foo
// results in the same syntax error: unexpected_token
Run Code Online (Sandbox Code Playgroud)

同理:

{foo: 'bar'}['foo']
// returns the new Array ['foo']
Run Code Online (Sandbox Code Playgroud)

这似乎证明了对象文字被忽略并且执行了尾随代码.

但是,这些工作正常:

({foo: 'bar'}).foo
// 'bar'

({foo: 'bar'})['foo']
// 'bar'
Run Code Online (Sandbox Code Playgroud)

括号用于运行代码行,并且由于该括号运算符的结果是实例化对象,因此可以访问属性.

那么,为什么忽略对象定义而不立即执行?

Arn*_*anc 8

它没有被忽略,它只是不被认为是一个对象.

{ ... }在语句的开头被解析为代码的[spec].

在这种情况下{foo: 'bar'}.foo,内部代码foo: "bar"被解析为LabelledStatement [spec].

因此{foo: 'bar'}正确解析(即使它没有按预期执行)但属性访问语法实际上导致语法错误,因为访问块上的属性无效.


正如您所注意到的那样,解决方案是将对象括在括号中:

({foo: 'bar'}).foo
Run Code Online (Sandbox Code Playgroud)

启动语句(会导致解析器在括号内搜索表达式.{foo: 'bar'}解析为表达式时,正如您所期望的那样是一个Object Initializer [spec].


因为{foo: 'bar'}['foo'],它实际上被解析为两个单独的语句:一个块({foo: 'bar'}和一个数组初始化器(['foo']):

{foo: 'bar'};
['foo'];
Run Code Online (Sandbox Code Playgroud)

  • 是的,因为错误状态 - 这是一个语法错误.正确的语法是使用括号. (2认同)
  • {foo:'bar'} ['foo']情况下没有语法错误,正如我上面提到的那样.它返回数组['foo'],好像我只是运行代码['foo'],来实例化一个数组['foo']. (2认同)

CMS*_*CMS 6

这是"背景"的问题,你的前两个例子不是对象文字!

它们是语句块,例如:

{ foo: 'bar' }
Run Code Online (Sandbox Code Playgroud)

上面的代码被评估为一个块,包含一个指向表达式语句(字符串文字)的带标签的语句().foo'bar'

当您将它包装在括号上时,代码将在表达式上下文中进行计算,因此语法与Object Literal语法匹配.

实际上还有其他方法可以强制进行表达式求值,并且您会看到属性访问符号在直接应用于对象文字时有效,例如:

({foo:'bar'}.foo);  // 'bar'
0, {foo:'bar'}.foo; // 'bar'
0||{foo:'bar'}.foo; // 'bar'
1&&{foo:'bar'}.foo; // 'bar'
// etc...
Run Code Online (Sandbox Code Playgroud)

现在在你的第二个例子中:

{foo: 'bar'}['foo']
Run Code Online (Sandbox Code Playgroud)

这里发生的是评估两个语句,首先是块,然后是包含Array文字的表达式语句.

语法歧义是否类似于函数表达式与函数声明所发生的情况.

也可以看看: