错误在没有超时的情况下遍历JavaScript中的大型数组

时间:2013-11-12 18:40:49

标签: javascript node.js

当我在Node.js中执行以下代码时,我收到了以下错误:

RangeError: Maximum call stack size exceeded

这是代码:

var arr = [];
for (var i = 0; i <= 1000000; i++)
    arr.push(i);

function nextStep(index) {
    if (index === arr.length) {
        return;
    } else {
        console.log(index);
    }
    nextStep(++index);
}

nextStep(0);

我不知道发生了什么,但是在索引= 17938附近,执行终止。

使用setTimeout()有帮助。这可能有什么问题?

3 个答案:

答案 0 :(得分:7)

您正在输入递归功能。这意味着在返回所有其他函数之前,第一个函数不会返回。所以如果你有四个项目,

fn(item1)
    calls ->  fn(item2)
                  calls ->  fn(item3)
                                calls ->  fn(item4)

正如您所看到的,嵌套会逐渐增加。这称为堆栈。堆栈有一个最大大小,以防止无限递归和失控进程。您已在17938找到它。

这是递归的固有缺陷。它可以是一种处理任务的时尚方式,但它有其局限性。纠正它的最好方法是改用循环:

for (var i = 0; i < arr.length; i++) {

使用setTimeout也有效,因为函数本身不会调用该函数,而是使用新堆栈执行。但是,它的性能要比循环或正常的递归函数低得多。

答案 1 :(得分:0)

在nextStep中调用nextStep导致堆栈溢出,因为你永远不会从函数返回(除非你找到数组的末尾,如果数组太大,你将永远不会到达它,直到堆栈溢出)。

一个例子: 你将把所有的石头从一个地方移到另一个地方。你的功能就像去石头的地方,拿起一块送到另一个地方。但是在你交付石头之前,你必须拿起另一块石头,在你交付之前你需要拿起另一块石头......很快你就会携带17938块石头了。这有点重,你会在所有的石头下被压碎。 (或者在javascript的情况下,你得到一个例外)

当你使用setTimetout时,就像你要去那个地方,拿起一块石头,并记下你应该拾取另一块石头。然后你送石头。之后,你看看你的笔记,看看你应该在石头上拾起。你可以这样做100万次,因为你一次只携带一块石头。

答案 2 :(得分:0)

根据不同浏览器的调用堆栈,可以进行一定数量的调用。最有可能的是,您正在Chrome中测试您的代码,因为我相信它的调用堆栈接近20.000。您的代码将执行nextStep函数超过20.000次(1百万),这意味着如果您的函数在达到该特定浏览器的调用堆栈限制之前不会返回某些内容,则会生成您的错误获得。