超时覆盖数据(JS)

时间:2014-02-20 08:59:58

标签: javascript asynchronous timeout

我有一个循环使用不同的超时间隔调用具有不同参数的函数三次:

<script type="text/javascript">
    var myArray = [];

    for (i=0; i<3; i++) {
        myArray[i] = [];
        myArray[i]['second'] = (1+i)*3000;
        myArray[i]['valeur'] = i+i;

        setTimeout(function() {
            otherfunction(myArray[i]['valeur']);
        }, myArray[i]['second']);
    }

    function otherfunction(data1) {
        console.log(data1);
    }
</script>

脚本正确调用otherfunction(),但出现错误:

  

未捕获的TypeError:无法读取未定义的属性'valeur'

我该如何解决这个问题。看起来像是有关变量范围的问题。

2 个答案:

答案 0 :(得分:4)

改变它:

for (i=0; i<3; i++)
{

    myArray[i] = new Array();
    myArray[i]['second'] = (1+i)*3000;
    myArray[i]['valeur'] = i+i;


    var timeoutCallback = (function(valeur){
        return function(){
            otherfunction(valeur);
        }
    })(myArray[i]['valeur']);

    setTimeout(timeoutCallback, myArray[i]['second']);


}

这里的要点是使用JavaScript closures来保持变量的当前值在范围内,对于像函数一样的回调。

如你所见,我们在这里有2个嵌套函数,第一个创建一个安全范围来保持当前值myArray[i]['valeur'],这完全取决于变量i,这在你的for循环中没有有一个固定的值。

有关查看此问题的详细信息,这是有史以来最有价值的答案:

How do JavaScript closures work?

答案 1 :(得分:0)

那是因为在超时功能中

i

变量已经是3,并且您的数组长度为3,因此myArray [3]未定义。您需要确保传递给setTimeout的函数在正确的值上有一个闭包。

这将有效:

var myArray = new Array();

for (i=0; i<3; i++)
{

    myArray[i] = new Array();
    myArray[i]['second'] = (1+i)*3000;
    myArray[i]['valeur'] = i+i;



    (function(val){
        setTimeout(function() 
        {
            otherfunction(val);
        },myArray[i]['second']);
    })(myArray[i]['valeur']);
}


function otherfunction(data1)
{
    console.log(data1);
}