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

时间:2009-06-08 11:10:10

标签: javascript json eval

我已经学会了(艰难的)我需要在JSON数据周围添加括号,如下所示:

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

(至少在Firefox 3中)。

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

7 个答案:

答案 0 :(得分:62)

eval接受一系列Javascript语句。 Javascript解析器 解释'{'标记,在语句中作为块的开头而不是对象文字的开头。

当您将文字括在这样的括号中时:({ data_from_the_wire }) 您正在将Javascript解析器切换到表达式解析模式。表达式中的标记“{”表示对象文字声明的开头,一个块,因此Javascript接受它作为对象文字。

答案 1 :(得分:38)

将括号括在data_from_the_wire附近实际上等同于

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

如果您在没有括号的情况下进行评估,那么将对代码进行评估,如果您在其中确实有任何已命名的函数,则会定义这些函数,但不会返回。

以一个函数调用函数的方式为例:

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

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

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

因此我们看到括号有效地将代码转换为返回的表达式,而不仅仅是要运行的代码。

答案 2 :(得分:11)

我不确定原因,但我使用the JSON class中的json.org来解析JSON。它比使用eval更安全。

答案 3 :(得分:9)

在JavaScript中,花括号用于创建块语句:

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

上面的行可以放在一个字符串中eval没有问题。现在考虑一下:

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

花括号使JavaScript引擎认为它是一个组表达式,因此围绕:字符的语法错误。引自MDN...JavaScript Guide...Object Literals

  

您不应在语句的开头使用对象文字。   这将导致错误或不按预期行事,因为{   将被解释为一个块的开始。

将对象文字包装在()中的解决方法是通过告诉引擎将其内容视为表达式而不是块语句来实现。所以这不起作用:

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

但这样做:

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

答案 4 :(得分:2)

这是因为没有圆括号JavaScript会尝试将{"text": ...解释为a label并失败。在控制台中尝试它,你会得到“无效标签”错误。

答案 5 :(得分:1)

实际上,它取决于data_from_the_wire的值。在大多数情况下,您的语法都可以,但是以{开头的行被解析为标签,而您的语法无效。如果用括号括起来,它会阻止解析器误解你的表达式。

真的只是一个解析问题。使用字符串,数字或函数,您就不会遇到这个问题。

一种解决方案是始终评估指令而不是表达式。你可以写

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

答案 6 :(得分:-2)

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

这种猜测会导致downvotes虽然=)。

修改

道格拉斯·克罗克福德在他的JSON网站上提到了语法歧义,但这对我没有帮助。