为什么Array不能在控制台中运行?

时间:2014-02-18 20:41:12

标签: javascript

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而不是元素的名称。我在这做错了什么?

5 个答案:

答案 0 :(得分:3)

一个非常常见的问题:回调是异步执行的,但使用的最后一个设置值为i。事件链是:

  • 你的循环设置了多个超时
  • 循环结束,i的值为8
  • 超时触发,并执行console.log(animel[i]),其中i8

为避免您需要断开与i

的闭包连接
setTimeout((function (index) {
    return function () { console.log(animel[index]); }
})(i), 2000);

答案 1 :(得分:2)

setTimeout内的函数引用相同的i值。因此,对于每一个,i都是8

您需要创建一个闭包来“捕获”i值。

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

答案 2 :(得分:2)

数组没有问题,问题是你如何关闭变量i

当函数执行时(循环完成后2秒),i增加超出animel的范围。简单的解决方案是提供isetTimeout的当前值,并将其作为函数中的参数接收,如下所示:

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

如果你需要在IE上支持这种语法< 9,MDN article提供了几种polyfill技术。

答案 3 :(得分:1)

这是一个JS机箱候选者。 i范围中使用的setTimeout的值不是您在使用时所考虑的值。要在超时发生时强制使用i的实际值,可以使用i作为常量而不是迭代器的方式使用它周围的空间。

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

DEMO

答案 4 :(得分:0)

你将它包装在一个setTimeout函数中,这是一个非阻塞操作。当循环完成时,我已经增加到一个破坏循环的值,并且超出了数组的范围。