JavaScript语法疯狂-有人知道为什么会发生这种情况吗?

3

我很困惑以下代码为什么会以这种方式执行。

对于下面的表达式,我期望结果为1,因为在字面量的右侧我们实际上有一个对象。

表达式:

> { a : 1 }.a 

谷歌浏览器的结果:

Syntax error: Unexpect token .

NodeJS 结果

1

(另一个问题是:为什么nodejs和chrome在这个问题(以及接下来的问题)上有所不同)

虽然表达式本身存在语法错误,但将其赋值给变量仍然有效。

> var x = { a : 1 }.a; x;

结果:

1

现在在Chrome和NodeJS中,使用eval来处理表达式确实可以工作。
> eval({ a : 1 }.a)

Chrome和Node的结果

1

现在使用eval和基于字符串的表达式,两个平台都无法正常工作。

eval("{ a : 1 }.a")

结果:Chrome:

SyntaxError: Unexpected token >

NodeJS 的结果:

... //REPL waits more code

最后,括号解决了所有问题,但为什么呢?
> eval("({ a : 1 }.a)")

结果:

Works everywhere

尝试使用父级括号(不要使用eval):({ a : 2 }.a) // 2 - karim79
1
@PeterAronZentai eval 代码总是在语句上下文中运行,这就是为什么你需要 eval("(" + code + ")" ) 在表达式上下文中运行代码的原因。例如,如果 code"{a:1}",那么将被评估的是 "({a:1})",因为括号是连接在一起的。 - Esailija
@PeterAronZentai 因为那不是一个字符串。eval只接受一个字符串。如果你传递一个非字符串,它将在执行之前被转换为字符串。所以 String({ a : 1 }.a)"1",而 "1" 将作为代码被执行。 - Esailija
啊哈,我现在明白了。因为转换进入表达式模式,对吧? - Peter Aron Zentai
@PeterAronZentai 这个转换并没有改变任何东西,你传递了一个无效的参数并且它被转换成了字符串。你最终会得到字符串 "1",所以代码实际上就是 1。将 1 作为 JavaScript 代码进行评估的结果是 1。 :P - Esailija
显示剩余2条评论
2个回答

8

eval接受一个字符串参数,所以调用eval({ a : 1 }.a)与调用eval("1")是相同的。

在语句上下文中,{}表示代码块而不是对象字面量。你可以通过使用()作为分组运算符来进入表达式上下文。

因此:

{ a : 1 }.a

实际上是一个块、标签、数字字面量和对空的点访问:

{
   a:  1
}

.a

Node REPL实际上一开始就在表达式上下文中运行,但这很不寻常。它们会像这样运行您的代码:eval("(" + replInput + ")")


是的,这使得它非常清晰易懂。主要区别在于我们所感知的控制台提示的实现方式。当然,语句和表达式上下文之间的明显区别以及括号在切换中的作用才是真正的知识。谢谢。 - Peter Aron Zentai

1
尝试 ({ a : 1 }).a 这个表达式。由于圆括号中的代码会先执行,然后从该对象中提取.a,所以这在任何地方都适用。
`{ a:  1 }`

这只是一个块,没有返回任何东西供.运算符使用,但将其放在()中会返回一个对象,其中提取了.a


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接