我正在尝试构建一个网页,我需要在JavaScript中搜索几个100MB的数据。对于不同的浏览器,我在不同的数据量下遇到“超出最大调用堆栈大小”错误。
我是否可以通过查看代码并尝试将函数内的局部变量移动到更全局的范围来尝试将它们分配到堆而不是堆栈来解决此问题?或者JavaScript中不存在这些概念? (据我所知,我的数据中没有任何主要的递归循环,所以它确实是一些巨大的字符串/数字数组似乎导致错误)
如果无法做到这一点,有没有办法让浏览器保留更多内存?
答案 0 :(得分:27)
好的,找出问题所在。我的代码中确实没有递归。如果它们是“varargs”函数,例如<array>.splice(...)
,这是我的罪犯,确实可以调用带有数百个参数的JavaScript函数。
除此之外:GWT以一种或多或少的聪明方式使用JavaScript拼接功能实现Java函数System.arraycopy(...)
。
splice接受任意数量的输入元素以插入目标数组。可以使用以下构造从另一个数组传递这些输入元素:
var arguments = [index, howmany].concat(elements);
Arrays.prototype.splice.apply(targetarray, arguments);
这相当于调用:
targetarray.splice(index, howmany, elements[0], elements[1], elements[2], ...);
如果元素变大(请参阅下面的“大”对不同浏览器的意义),可以获得“超出最大调用堆栈大小”错误没有递归,因为它的内容将被加载到函数调用的堆栈中。
这是一个演示此问题的简短脚本:
var elements = new Array();
for (i=0; i<126000; i++) elements[i] = 1;
try {
var arguments = [0, 0].concat(elements);
Array.prototype.splice.apply(elements, arguments);
alert("OK");
} catch (err) {
alert(err.message);
}
使用此脚本,“big”表示以下内容:
获胜者是:Internet Explorer 8进行更改!在此函数调用失败之前,它可以用尽所有系统内存。
旁注:Firefox和Opera实际上抛出了一个不同的(更有用的)错误消息:Function.prototype.apply:argArray太大
答案 1 :(得分:16)
Javascript中没有内存分离到堆栈/堆中。你看到的可能是以下之一: