我已经(艰难地)了解到我需要在 JSON 数据周围添加括号,如下所示:
stuff = eval('(' + data_from_the_wire + ')');
// where data_from_the_wire was, for example {"text": "hello"}
(至少在 Firefox 3 中)。
这背后的原因是什么?我讨厌在不了解幕后内容的情况下编写代码。
我已经(艰难地)了解到我需要在 JSON 数据周围添加括号,如下所示:
stuff = eval('(' + data_from_the_wire + ')');
// where data_from_the_wire was, for example {"text": "hello"}
(至少在 Firefox 3 中)。
这背后的原因是什么?我讨厌在不了解幕后内容的情况下编写代码。
eval
接受一系列 Javascript 语句。Javascript 解析器将出现在语句中的“{”标记解释为块的开头,而不是对象文字的开头。
当您将文字括在这样的括号中时:({ data_from_the_wire })
您正在将 Javascript 解析器切换到表达式解析模式。表达式中的标记“{”表示对象字面量声明的开始,而不是块,因此 Javascript 将其作为对象字面量接受。
将括号放在周围data_from_the_wire
实际上等效于
stuff = eval('return ' + data_from_the_wire + ';');
如果您要在不带括号的情况下进行 eval,则将评估代码,并且如果您在其中确实有任何命名函数,则这些函数将被定义,但不会返回。
以在创建函数时调用函数的能力为例:
(function() { alert('whoot'); })()
将调用刚刚定义的函数。但是,以下内容不起作用:
function() { alert('whoot'); }()
因此,我们看到括号有效地将 then 代码转换为返回的表达式,而不仅仅是要运行的代码。
在 JavaScript 中,大括号用于创建块语句:
{
var foo = "bar";
var blah = "baz";
doSomething();
}
上面的行可以放在一个字符串中并eval
没有问题地使用。现在考虑一下:
{
"foo": "bar",
"blah": "baz"
}
花括号导致 JavaScript 引擎认为它是一个组表达式,因此:
字符周围的语法错误。引用MDN...JavaScript 指南...对象文字:
您不应该在语句的开头使用对象字面量。这将导致错误或行为不符合您的预期,因为 { 将被解释为块的开头。
将对象文字包装在内部的解决方法是()
告诉引擎将其内容视为表达式,而不是块语句。所以这不起作用:
({
var foo = "bar";
var blah = "baz";
doSomething(evil);
})
// parse error
但这确实:
({
"foo": "bar",
"blah": "baz"
})
// returns object
发生这种情况是因为没有圆括号 JavaScript 试图解释{"text": ...
为标签并失败。在控制台中尝试,您将收到“无效标签”错误。
data_from_the_wire
实际上,这取决于 的值。在大多数情况下,您的语法是可以的,但是以开头的行{
被解析为标签,而您的则无效。如果你用括号括起来,它可以防止解析器误解你的表达式。
只是一个解析问题,真的。使用字符串、数字或函数,您就不会有这个问题。
一种解决方案是始终评估指令而不是表达式。你可以写
eval('var stuff = {"text": "hello"}');
我不知道,我实际上对这个问题的答案很感兴趣,但我的猜测是,如果没有括号,其中的数据data_from_the_wire
将被解释为闭包。也许括号强制评估,因此关联数组被“返回”。
虽然这种猜测会导致投反对票=)。
编辑
Douglas Crockford 在他的JSON网站上提到了语法歧义,但这并没有真正帮助我。