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

发布于 2024-07-23 05:31:57 字数 250 浏览 7 评论 0 原文

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

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

至少在 Firefox 3 中)。

这背后的原因是什么? 我讨厌在不了解其背后的含义的情况下编写代码。

I've learned (the hard way) that I need to add parentheses around JSON data, like this:

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

(In Firefox 3, at least).

What's the reason behind this? I hate writing code without understanding what´s behind the hood.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

も让我眼熟你 2024-07-30 05:31:57

eval 接受一系列 Javascript 语句。 JavaScript 解析器
将语句中出现的“{”标记解释为块的开头,而不是对象字面量的开头。

当您将文字括在括号中时,如下所示:({ data_from_the_wire })
您正在将 Javascript 解析器切换到表达式解析模式。 表达式中的标记“{”表示对象字面量声明的开始,而不是块,因此 Javascript 将其视为对象字面量。

eval accepts a sequence of Javascript statements. The Javascript parser
interprets the ‘{’ token, occuring within a statement as the start of a block and not the start of an object literal.

When you enclose your literal into parentheses like this: ({ data_from_the_wire })
you are switching the Javascript parser into expression parsing mode. The token ‘{’ inside an expression means the start of an object literal declaration and not a block, and thus Javascript accepts it as an object literal.

八巷 2024-07-30 05:31:57

将括号放在 data_from_the_wire 周围实际上相当于

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

如果您要在不带括号的情况下进行评估,则将对代码进行评估,并且如果您确实在其中包含任何命名函数,则这些函数将被定义,但不会返回。

以在创建函数时调用函数的能力为例:

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

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

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

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

Putting the parentheses around data_from_the_wire is effectively equivalent to

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

If you were to eval without the parentheses, then the code would be evaluated, and if you did have any named functions inside it those would be defined, but not returned.

Take as an example the ability to call a function just as it han been created:

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

Will call the function that has just been defined. The following, however, does not work:

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

So we see that the parentheses effectively turn then code into an expression that returns, rather than just code to run.

回眸一遍 2024-07-30 05:31:57

我不确定原因,但我使用 JSON 类解析 JSON 来自 json.org。 它比使用 eval 安全得多。

I'm not sure of the reason but I parse JSON by using the JSON class from json.org. It's much safer than using eval.

樱花坊 2024-07-30 05:31:57

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

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

上面的行可以放入字符串内并毫无问题地进行评估。 现在考虑一下:

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

大括号导致 JavaScript 引擎认为它是一个组表达式,因此 : 字符周围出现语法错误。 引用自 MDN...JavaScript 指南...对象文字

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

将对象文字包装在 () 内的解决方法是告诉引擎将其内容视为表达式,而不是块语句。 所以这行不通:

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

但是这行得通:

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

In JavaScript, curly brackets are used to create block statements:

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

The above lines can be put inside a string and evaluated without problem. Now consider this:

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

The curly brackets cause the JavaScript engine to think it is a group expression, hence the syntax error around the : character. Quote from MDN...JavaScript Guide...Object Literals:

You should not use an object literal at the beginning of a statement.
This will lead to an error or not behave as you expect, because the {
will be interpreted as the beginning of a block.

The workaround of wrapping the object literal inside () works by telling the engine to treat its contents as an expression, not as a block statement. So this does not work:

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

But this does:

({
"foo": "bar",
"blah": "baz"
})
// returns object
对你的占有欲 2024-07-30 05:31:57

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

This happens because without round braces JavaScript tries to interpret {"text": ... as a label and fails. Try it in console and you'll get "invalid label" error.

尾戒 2024-07-30 05:31:57

实际上,这取决于 data_from_the_wire 的值。 在大多数情况下,您的语法没问题,但以 { 开头的行被解析为标签,而您的语法无效。 如果用括号将其括起来,可以防止解析器误解您的表达式。

实际上只是一个解析问题。 使用字符串、数字或函数,就不会有这个问题。

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

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

It depends on the value of data_from_the_wire, actually. In most cases your syntax is ok, but a line that begins with { is parsed as a label, and yours is invalid. If you surround it with parenthesis, it prevents the parser from misinterpreting your expression.

Just a parsing problem, really. With strings, numbers or functions, you wouldn't have that problem.

One solution is to always eval instructions and not expressions. You can write

eval('var stuff = {"text": "hello"}');
烟雨凡馨 2024-07-30 05:31:57

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

这种猜测会导致投反对票=)。

编辑

Douglas Crockford 在他的 JSON 网站上提到了语法歧义,但是并没有真正帮助我。

I don't know, and I am actually interested in the answer to this, but my guess is that without the parentheses the data in data_from_the_wire would be interpreted as a closure. Maybe the parentheses force evaluation and so the associative array is 'returned'.

This is the kind of guessing that leads to downvotes though =).

EDIT

Douglas Crockford mentions a syntax ambiguity on his JSON site but that didn't really help me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文