2014-02-18 62 views
0
var animel = new Array(); 

animel[0] = 'cat'; 
animel[1] = 'dog'; 
animel[2] = 'horse'; 
animel[3] = 'cow'; 
animel[4] = 'elephant'; 
animel[5] = 'tiger'; 
animel[6] = 'lion'; 
animel[7] = 'fish'; 

for (var i = 0; animel.length > i; i++) { 
    setTimeout(function() { 

     console.log(animel[i]); 

    }, 2000); 

} 

當我在控制檯中執行此代碼時,它會記錄undefined而不是元素的名稱。我在這做錯了什麼?爲什麼Array不能在控制檯中工作?

+6

我不想編輯您的帖子對什麼都沒有,但它的** **的動物。該帖子的其餘部分是:) – Lix

+1

animel [8]將始終未定義,計數器'i'在settimeout觸發器時已經遞增。 –

+1

在這個'動物'拼寫錯誤和*所有*的答案是真的困擾我>。 nzifnab

回答

2

setTimeout中的功能引用相同的i值。所以對於每一個,i8

您需要創建一個閉包以「捕獲」i值。

var createFunc = function(i){ 
    return function(){ 
     console.log(animel[i]); 
    }; 
}; 
for (var i = 0; animel.length > i; i++) { 
    setTimeout(createFunc(i), 2000); 
} 
2

這個數組沒有問題,問題在於如何關閉變量i

當函數執行時(循環完成後2秒)i已經增加到animel的範圍之外。最簡單的辦法是提供i當前值setTimeout並接受其作爲函數的參數,就像這樣:

for (var i = 0; animel.length > i; i++) { 
    setTimeout(function (i) { 
     console.log(animel[i]); 
    }, 2000, i); 
} 

如果需要支持IE < 9這句法中,MDN article提供了幾個填充工具技術。

+0

爲什麼你通過'我''setTimeout'?那會做什麼? –

+0

@RocketHazmat ['window.setTimeout'](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)接受參數在執行時傳遞給函數。 –

+0

雖然瀏覽器不兼容,但顯着的IE瀏覽器<9。 – deceze

0

你正在將它封裝在一個非阻塞操作的setTimeout函數中。到循環完成時,我已經增加到一個打破循環並超出數組界限的值。

3

一個非常普遍的問題:回調是異步執行的,但使用最後一個設置值i。事件的鏈條是:

  • 你的循環設置了許多超時
  • 循環結束的,i的值是8
  • 超時火,並執行console.log(animel[i]),其中i8

爲避免您需要將關閉連接中斷至i

setTimeout((function (index) { 
    return function() { console.log(animel[index]); } 
})(i), 2000); 
+5

哇...這樣的代碼...所以括號...多關閉... – Lix

+2

(我(想)我是(一(Lisp((((開發人員))在)前)生活)) )。 – deceze

1

這是一個JS候選人。在setTimeout範圍中使用的i的值不是您在使用時認爲的值。爲了在超時發生時強制使用i的實際值,可以使用i作爲常量而不是迭代器的方式在其周圍使用機箱。

for (var i = 0; i<animel.length; i++) { 
    (function(x){ 
     setTimeout(function() { 
      console.log(animel[x]); 
     }, 500); 
    })(i); 
} 

DEMO

相關問題