为什么JavaScript的eval需要括号来评估JSON数据?

我已经了解到了(困难的方法),我需要在JSON数据中添加括号,如下所示:

stuff = eval('(' + data_from_the_wire + ')'); // where data_from_the_wire was, for example {"text": "hello"} 

(在Firefox 3中,至less)。

这背后的原因是什么? 我讨厌编写代码而不理解引擎盖后面的内容。

围绕data_from_the_wire放置括号实际上等同于

 stuff = eval('return ' + data_from_the_wire + ';'); 

如果你不用括号来评估,那么代码将被评估,如果你确实有任何命名的函数,那么这些代码将被定义,但是不会被返回。

举一个例子,就像调用一个函数一样:

 (function() { alert('whoot'); })() 

将调用刚刚定义的函数。 但是,以下内容不起作用:

 function() { alert('whoot'); }() 

所以我们看到括号有效地将代码转换成返回的expression式,而不仅仅是代码运行。

eval接受一系列Javascript语句。 Javascriptparsing器将“{”标记解释为一个块的开始,而不是对象字面的开始。

当你把你的文字括入这样的括号: ({ data_from_the_wire })你正在把JavaScriptparsing器切换到expression式parsing模式。 expression式中的标记“{”意味着对象字面声明的开始而不是块,因此JavaScript将其作为对象字面值来接受。

我不确定的原因,但我使用json.org 的JSON类来parsingJSON。 这比使用eval更安全。

在JavaScript中,大括号用于创build块语句:

 { var foo = "bar"; var blah = "baz"; doSomething(); } 

上面的几行可以放在一个string中,并且没有问题的eval 。 现在考虑一下:

 { "foo": "bar", "blah": "baz" } 

花括号使JavaScript引擎认为它是一个组expression式,因此在:字符周围的语法错误。 引用来自MDN … JavaScript指南…对象文字 :

您不应该在语句的开头使用对象字面值。 这将导致一个错误或不像你期望的行为,因为{将被解释为一个块的开始。

()中封装对象字面值的解决方法是通过告诉引擎将其内容视为expression式来处理,而不是作为块语句。 所以这不起作用:

 ({ var foo = "bar"; var blah = "baz"; doSomething(evil); }) // parse error 

但是这样做:

 ({ "foo": "bar", "blah": "baz" }) // returns object 

发生这种情况是因为没有使用圆括号,JavaScript尝试将{"text": ...解释为标签并失败。 在控制台中试用,你会得到“无效标签”的错误。

实际上这取决于data_from_the_wire的价值。 在大多数情况下,你的语法是可以的,但是一个以{开头的行被parsing为一个标签,而你的是无效的。 如果用圆括号括起来,它可以防止parsing器误解你的expression式。

只是一个parsing问题,真的。 用string,数字或函数,你不会有这个问题。

一个解决scheme是总是评估指令而不是expression式。 你可以写

 eval('var stuff = {"text": "hello"}'); 

我不知道,实际上我对这个答案感兴趣,但我的猜测是,没有括号, data_from_the_wire中的数据将被解释为闭包。 也许括号强制评估,所以关联数组是“返回”。

这是猜测,导致downvotes虽然=)。

编辑

道格拉斯·克罗克福德(Douglas Crockford)在他的JSON网站上提到了一个语法模糊的问题,但这并没有真正帮助我。