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

Tom*_*omo 34 javascript json eval

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

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

(至少在Firefox 3中).

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

kar*_*m79 63

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

当您将文字括在这样的括号中时:({ data_from_the_wire }) 您正在将Javascript解析器切换到表达式解析模式.表达式中的标记"{"表示对象文字声明的开头而不是块,因此Javascript将其接受为对象文字.


Kaz*_*zar 39

把括号括起来data_from_the_wire实际上相当于

stuff = eval('return ' + data_from_the_wire + ';');
Run Code Online (Sandbox Code Playgroud)

如果你没有括号的eval,那么代码将被评估,如果你在其中有任何命名函数,那么将定义,但不返回.

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

(function() { alert('whoot'); })()
Run Code Online (Sandbox Code Playgroud)

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

function() { alert('whoot'); }()
Run Code Online (Sandbox Code Playgroud)

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

  • 第一部分并不完全正确; eval将字符串解释为顶级代码,因此返回不起作用.函数的问题类似于原始问题,因为它是函数*语句*和函数*表达式*之间的歧义(参见karim79的答案). (4认同)
  • 我真的认为这个答案是不完整的,为什么JSON文字作为`eval()`的参数,必须括在括号中.@ karim79的答案更明确:JSON文字的`{...}`将被解析为块而不是对象文字(它应该是). (4认同)

Gar*_*ler 11

我不知道原因,但我解析JSON使用JSON的类json.org.它比使用eval更安全.

  • 为什么选择downvote?这似乎是一个有效的答案.使用eval是不安全的. (5认同)
  • @TimČas我意识到我没有直接回答这个问题,但当有人用枪指着他们为什么需要取消安全时,我首先建议他们用枪指着你的脚可能不是一个好主意. (3认同)
  • 是的,但如果我问安全气囊是如何工作的,那么正确的答案就是描述它们是如何工作的,而不是说撞坏汽车是坏事:) (3认同)

Sal*_*n A 9

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

{
var foo = "bar";
var blah = "baz";
doSomething();
}
Run Code Online (Sandbox Code Playgroud)

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

{
"foo": "bar",
"blah": "baz"
}
Run Code Online (Sandbox Code Playgroud)

花括号使JavaScript引擎认为它是一个组表达式,因此:字符周围的语法错误.从MDN引用... JavaScript指南...对象文字:

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

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

({
var foo = "bar";
var blah = "baz";
doSomething(evil);
})
// parse error
Run Code Online (Sandbox Code Playgroud)

但这样做:

({
"foo": "bar",
"blah": "baz"
})
// returns object
Run Code Online (Sandbox Code Playgroud)