为什么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网站上提到了一个语法模糊的问题,但这并没有真正帮助我。