2010-09-17 72 views
4

最近我遇到了一个问题:传递给eval()函数时有效的JSON导致它抛出错误 - “脚本堆栈空间配额已耗尽”。JavaScript函数eval()抛出堆栈外配额异常

它始终可以重现,并且通过初步检查,似乎这是可以定义的对象属性/属性数量的限制(而不是内容的大小)。

这里的示例代码:

function starttest() 
{  
     var d = new Array(50000); 
     var i = 0; 

     for (i = 0; i < d.length; i++) { 
      d[i] = new Object(); 
      d[i].a1 = 1; 
      d[i].a2 = 2; 
      d[i].a3 = i; 
      d[i].a4 = i; 
      d[i].a5 = i; 
      d[i].a6 = i; 
      d[i].a7 = i; 
      d[i].a8 = i; 
      d[i].a9 = i; 
      d[i].a10 = i; 
      d[i].a11 = i; 
      d[i].a12 = i; 
      d[i].a13 = i; 
      d[i].a14 = i; 
      d[i].a15 = i; 
     }  



    var jsonString = JSON.stringify(d); 
    alert(jsonString.length); 

    var obj = eval(jsonString); 
    var count = 0; 
    for(var i = 0; i< obj.length; i++) { 

     for (var k in obj[i]) { 
      if (obj[i].hasOwnProperty(k)) { 
       ++count; 
      } 
     } 
    } 

    alert("Done! || Len: " + obj.length + " || " + "Attrib Count: " + count + " || " + typeof obj) 
} 

有趣的是,我可以定义比代码片段看到更多的对象;只有在使用eval()函数时才会出现问题。

对此的任何新见解都将非常有帮助。我知道使用eval()是不安全的,所有...我接受建议!

+1

FWIW,我在Chrome和IE 9(测试版)中测试了你的代码,它工作正常。在Firefox 3.6.8中超出堆栈空间。 – 2010-09-17 13:05:01

回答

1

是的,这是一般的Firefox的JavaScript解释器的问题。这不只是eval:如果你把五万行:

{a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,a2:1,b2:2,c2:3,d2:4,e2:5,f2:6,g2:7,h2:8,i2:9,j2:10}, 

在阵列中的一个普通的脚本文件或<script>元素的文字,你会得到完全同样的错误。

看来脚本块的复杂性受编译时JS_DEFAULT_SCRIPT_STACK_QUOTA的限制。请参阅420869及相关链接的错误。

这是相对不太可能的,你应该在正常情况下遇到这种情况。当然,对于JSON的情况,您可以使用JSON.parse,它不是完整的JavaScript解释器,不受此限制的影响。如果你需要一个不受影响的非有效的JSON JS文本分析器,我想你必须自己编写它......尽管当你输入这么长时间时它可能会令人生厌。

3

这意味着它说什么。 eval显然使用递归,并且在评估长而复杂的JSON文字时超出了限制。它适用于JSON.parse(至少在Firefox 3.6.11pre中),这是该作业的正确工具,并且often faster

+0

但是,请注意,如果您的浏览器不具有本地'JSON.parse',则http://www.json.org/json2.js中定义的实现在内部使用'eval',因此它将具有相同的问题。 'json_parse'(如Alex的答案中所提到的)不会。所以我会使用本机JSON解析(如果可用)和'json_parse'作为后备。 – 2010-09-17 13:05:59

1

它看起来像你正在使用JSON类来创建一个JSON字符串。为什么不使用相反的函数进行字符串化以将JSON恢复为对象语法?

http://www.json.org/json_parse.js - 是javsacript JSON类。只需调用json_parse(str);你会得到一个很好的对象。

正如你所说,eval()并不安全。这是该死的邪恶!