eval是邪恶的,但它有缺陷吗?

时间:2016-02-18 12:43:03

标签: javascript jquery json eval

如果我这样做:

var foo = {};
foo.ear = {};
foo.ear["<="] = 6;

我收到错误:

  

Uncaught SyntaxError:意外的令牌:

让我们手动创建对象:

JSON.stringify(foo)

现在,以下代码:

eval(JSON.stringify(foo))

返回以下字符串:

  

&#39; {&#34;耳&#34; {&#34;&LT; =&#34;:6}}&#39;

与我开始的字符串相同的字符串(白色字符除外,但这些字符串无关紧要),因此$.parseJSON(JSON.stringify(foo)) 返回相同的语法错误错误消息。但是:

stringify

正确执行。这是什么原因?

编辑:

正如nnnnnn和Ron Dadon指出的那样,初始字符串和stringify的结果是不同的。但是,正如我在问题中指出的那样,即使eval的结果用作function evalJSON(text) { return eval("(" + text + ")"); } 的输入,也会产生语法错误消息。

EDIT2:

根据所进行的答案和实验,这个功能很有意思:

stPopupWindow = new top.Ext.Window({
            title : title,
            id : 'stPopupWindowId', 
            x: 0,
            y: 0,
            width: screenWidth,
            height: screenHeight,
            draggable: false,modal:true,closeAction:'close',plain: true,
            layout:'fit',
            autoScroll:true,
            maximizable : true,
            minimizable : true,
            items:[...]});

3 个答案:

答案 0 :(得分:16)

{}被解析为block statement

尝试用括号括起来:

eval('({ear: {"<=": 6}})');

在javascript {}中可以解析为块或对象

的示例:

//object
var user = {
  name: "John",
  age: "32"
};

//block
{
   let a = 5;
   console.log(a);   
}

//object:
var a = {};
console.log({});
return {};
({});

//block:
function(){}
for(k in o){}
{}

答案 1 :(得分:7)

这没有缺陷。要了解发生了什么,您需要了解解析器看到的语句类型(从左到右)。

进入它的一个简单方法是使用Javascript AST Visualizer

  1. 您将使用更简单的{"b":4}获得相同的异常。它在block内被解析为"b":4。这不是有效的JavaScript。没有AST树给你...... 但是,这是由于{}语句中的异常所致。那是BlockStatement。 AST树:AST tree for {}

  2. 类似的{b:4}将被理解为b:4,一个有效的js语句 - b label用于4 ...已解析作为AST tree for {b:4}

  3. 最后,({b:4})将被理解为b属性等于4的对象声明。这被解析为AST tree for ({b:4})

  4. ECMAScript 2015

    Blocks上:

      

    阻止:{StatementList}

    eval上: Eval创建一个新的Realm,它被解析(这里有几个步骤)作为Statement s(StatementList)的序列,而this section依次为BlockStatement { }作为第一选择。这个必须({})开头(见上文),所以如果你用括号(BlockStatement)包裹它,不能是{{1但是......如果匹配为BlockStatement,则必须BlockStatement

    Expressions部分的旁注:

      

    ExpressionStatement不能以U + 007B(LEFT CURLY BRACKET)开头,因为这可能会使其与Block

    不一致

答案 2 :(得分:7)

需要评估对象文字符号。分配变量时会发生这种情况:

var a = {ear: {"<=": 6}};

或者在括号周围添加一个匿名对象:

({ear: {"<=": 6}});

否则,花括号将被解析为块标记。在您的情况下,这意味着{ear:...}是标签定义,标签名为ear。下一个块{"<=": 6}会出现语法错误,因为"<=": 6语法无效。

如果将其放入eval语句中,则同样适用。