2012-11-28 22 views
1

這裏是我正在嘗試做的。 我有類似下面的無法在setTimeout內正確訪問數組元素

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

我想要做的就是創建一批HTML元素的該陣列的每個元素,並自該陣列可包含的元素數量龐大的陣列I試圖執行以下操作,以便瀏覽器不會凍結。

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; 
}; 

請問有人可以幫我解決這個問題嗎?

回答

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

+0

我強烈建議打開工廠函數併爲'i'參數使用不同的名稱。這是非常混亂的閱讀,調試,確實理解不熟悉JS的人比我知道你是。 :-) –

+0

@ T.J.Crowder真的,不知道OP爲什麼接受它。 ; < – Esailija

+1

@ Esailija:它完成了這項工作! :-)(看起來他們的代碼只是一個小小的改變,如果你真的不知道發生了什麼......) –

2

的問題是,你正在創建的功能有參考i變量,而不是它的價值一個副本,因此,當他們跑他們看到i,因爲它是在那個時間點(超過陣列的末端,大概是)。 (更多:Closures are not complicated

我推薦一個完全不同的方法(下面),但首先,讓我們看看如何使現有的方法工作。

要做你正在嘗試做的事情,用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); 
    } 
} 
0

它只是一個猜測。試試吧,如:循環完成後執行

for(var i in my_array) 
{ 
    if(my_array.hasOwnProperty(i)) 
     setTimeout("do_something_with_data('"+my_array[i]+"')", 500); 
} 
+3

不要使用字符串作爲'第一個參數setTimeout' /'setInterval' – Andreas

+0

作爲一個澄清,使用字符串作爲第一個參數實際上是依賴於EVAL這是一件壞事文檔。 – ezis