当下面的代码中这个list数据很大时,为什么我的浏览器速度变慢:

var list = [];

/*
  Creating some huge dummy data
  Interstingly, when I change the value of i from 10000
  to 100000, the browser hangs(becomes unresponsive)
*/
for(i=0;i<10000;i++){
  list.push(i);

}

/*Recursive function*/
var nextListItem = function() {
    var item = list.pop();

    if (item) {
        console.log(item);
        // process the list item...
        nextListItem();
    }
};
nextListItem(); // Commented this as browser becomes unresponsive.

jsbin

我无法从Google那里找到我的问题的直接答案,因此尽管获得了SO专家的帮助。我以为它与浏览器内存有关,因为我可以看到循环以很高的速度开始,然后慢慢减慢并变得无响应。但不确定为什么吗?

最佳答案

JavaScript没有尾声消除功能。因此,如果您递归遍历列表,则会浪费大量资源。最终,您甚至可能会耗尽堆栈空间。

解决此问题的一种可能的方法是异步调用tail调用,以便main函数在tail调用函数开始执行之前完成执行。这样可以确保堆栈空间不会增加:

var list = [];

for (var i = 0; i < 10000; i++) list.push(i);

var start = new Date;

nextListItem();

function nextListItem() {
    var item = list.pop();

    if (item) {
        console.log(item);
        setTimeout(nextListItem, 0);
    } else console.log(new Date - start);
}


有关更多详细信息,请参见以下问题:

What's the difference between a continuation and a callback?

编辑:更快的解决方案(由T.J. Crowder建议):

var list = [];

for (var i = 0; i < 10000; i++) list.push(i);

var start = new Date;

nextListItem();

function nextListItem() {
    var item = list.pop();

    if (item) {
        console.log(item);
        if (item % 100) nextListItem();
        else setTimeout(nextListItem, 0);
    } else console.log(new Date - start);
}


循环更加缓慢,因为它以100个项目的突发打印到控制台。但是,它可以更快地完成执行。

10-07 13:49
查看更多