1

这就是我想要做的。我有一个像下面这样的数组

var my_array = ['1', '2', '3' ... ,'1000000000000000'];

我想要做的是为该数组的每个元素创建一堆 HTML 元素,并且由于该数组可以包含大量元素,我尝试执行以下操作,因此浏览器不会冻结。

for(var i in my_array)
{
    if(my_array.hasOwnProperty(i))
    {
       setTimeout(function(){
             do_something_with_data(my_array[i]);
       });
    }
 }

但发生的情况是 setTimeout 中的 my_array[i] 没有应有的值。

更准确地说,当我尝试console.log(my_array[i])得到的结果是这样的:

"getUnique" function (){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
}

getUnique 是我添加到 Array 原型中的一个函数,如下所示:

Array.prototype.getUnique = function(){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
};

有人可以帮我解决这个问题吗?

4

3 回答 3

3

setTimeout 在循环完成后执行,i是最后一个键或某个垃圾值。你可以像这样捕捉我:

for (var i in my_array) {
    if (my_array.hasOwnProperty(i)) {
        (function(capturedI) {
            setTimeout(function() {
                do_something_with_data(my_array[capturedI]);
            });
        })(i);
    }
}

您也不应该for..in对数组使用循环,因为它.hasOwnProperty比 for 循环慢一个数量级(尤其是检查时),并且没有定义迭代顺序

如果你有 jQuery 或者愿意为旧版浏览器添加一些额外的代码,你可以这样做:

my_array.forEach( function( item ) {
     setTimeout( function() {
         do_something_with_data( item );
     }, 1000);
});

使用 jQuery:

$.each( my_array, function( index, item ) {
     setTimeout( function() {
         do_something_with_data( item );
     }, 1000);
});

请参阅文档[].forEach

于 2012-11-28T15:04:50.490 回答
2

问题是您正在创建的函数具有对变量的引用i,而不是其value的副本,因此当它们运行时,它们会看到i当时的状态(大概是在数组末尾之后)。(更多:闭包并不复杂

我会推荐一种完全不同的方法(如下),但首先,让我们看看如何使您现有的方法发挥作用。

为了做你想做的事情,使用for循环,你必须让函数关闭一些不会改变的东西。通常的方法是使用工厂函数来创建超时函数,以便它们关闭工厂的参数。或者实际上,您可以传入数组元素的值而不是索引变量。

for(var i in my_array)
{
    if(my_array.hasOwnProperty(i))
    {
       setTimeout(makeFunction(my_array[i]));
    }
 }

function makeFunction(entry) {
    return function(){
        do_something_with_data(entry);
    };
}

但是,我可能会重组代码,这样您就不会不必要地创建大量的函数对象。相反,使用一个函数,并让它关闭它递增的索引:

// Assumes `my_array` exists at this point, and that it
// has at least one entry
var i = 0;
setTimeout(tick, 0);
function tick() {
    // Process this entry
    if (my_array.hasOwnProperty(i)) {
        do_something_with_data(my_array[i]);
    }

    // Move to next
    ++i;

    // If there are any left, schedule the next tick
    if (i < my_array.length) {
        setTimeout(tick, 0);
    }
}
于 2012-11-28T15:04:35.950 回答
0

这只是一个猜测。试试看:

for(var i in my_array)
{
    if(my_array.hasOwnProperty(i))
       setTimeout("do_something_with_data('"+my_array[i]+"')", 500);
}
于 2012-11-28T15:04:38.380 回答