技术“ eval()”和“ JSON.parse()”使用互斥格式。
- 使用“ eval()”时,必须带括号。
- 带有“ JSON.parse()”的括号被禁止。
当心,有些“ stringify()”函数会产生“ eval”格式。对于ajax,您应该仅使用JSON格式。
尽管“ eval”包含了整个JavaScript语言,但JSON仅使用了该语言的一小部分。在JavaScript语言中,“ eval”必须识别的构造是“ Block语句”(又称“ compound语句”);这是一对或大括号“ {}”,里面带有一些语句。但是在对象文字的语法中也使用花括号。解释通过代码出现的上下文来区分。在您看来,某些东西看起来像对象文字,但“ eval”会将其视为复合语句。
在JavaScript语言中,对象文字出现在分配的右侧。
var myObj = { ...some..code..here... };
对象文字不会单独出现。
{ ...some..code..here... } // this looks like a compound statement
回到OP在2008年提出的原始问题,他询问为什么以下内容在“ eval()”中失败:
{ title: "One", key: "1" }
答案是它看起来像一个复合语句。要将其转换为对象,必须将其置于不可能使用复合语句的上下文中。这是通过在其周围加上括号来完成的
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
OP还询问为什么类似的声明确实成功了:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
答案也相同-大括号位于不可能使用复合语句的上下文中。这是一个数组上下文,“ [...]
”,并且数组可以包含对象,但不能包含语句。
与“ eval()”不同,JSON的功能非常有限。该限制是有意的。JSON的设计者希望使用JavaScript的一个极简子集,仅使用可能出现在分配右侧的语法。因此,如果您有一些可以在JSON中正确解析的代码...
var myVar = JSON.parse("...some...code...here...");
……这也意味着它将合法地在作业的右侧进行解析,如下所示。
var myVar = ...some..code..here... ;
但这不是对JSON的唯一限制。JSON的BNF语言规范非常简单。例如,它不允许使用单引号来表示字符串(例如JavaScript和Perl这样做),并且它没有将单个字符表示为字节的方式(例如'C'那样)。不幸的是,它也不允许注释(在创建配置文件时会非常好)。所有这些限制的好处在于,解析JSON的速度很快,并且没有机会进行代码注入(安全威胁)。
由于这些限制,JSON不能用于括号。因此,JSON字符串中的括号是非法字符。
出于以下原因,请始终对ajax使用JSON格式:
- 将为JSON配置典型的ajax管道。
- 使用“ eval()”将被批评为安全隐患。
作为ajax管道的示例,请考虑一个涉及Node服务器和jQuery客户端的程序。客户端程序使用形式为的jQuery调用$.ajax({dataType:'json',...etc.});
。JQuery创建一个jqXHR对象供以后使用,然后打包并发送关联的请求。服务器接受请求,对其进行处理,然后准备响应。服务器程序将调用该方法res.json(data)
以打包并发送响应。回到客户端,jQuery接受响应,查询关联的jqXHR对象,并处理JSON格式的数据。所有这些都不需要手动数据转换。该响应不涉及节点服务器上对JSON.stringify()的显式调用,也不涉及客户端上的JSON.parse()的显式调用。一切都为您完成。
“ eval”的使用与代码注入的安全风险有关。您可能会认为不可能发生,但是黑客可以变得很有创造力。而且,“ eval”对于Javascript优化是有问题的。
如果确实使用“ stringify()”函数来使用,请注意,某些具有该名称的函数将创建与“ eval”而不是与JSON兼容的字符串。例如,在Node中,以下代码为您提供了以“ eval”兼容格式创建字符串的功能:
var stringify = require('node-stringify'); // generates eval() format
这可能很有用,但是除非您有特定需要,否则可能不是您想要的。