JS:setTimeout始终打印上次迭代的值

时间:2014-08-12 11:27:02

标签: javascript arrays loops object

我知道这个问题与JS范围有关,我已经搜索过,但无法让other stackoverflow questions的解决方案起作用。

我有这个程序

http://jsfiddle.net/0z525bhf/

function write(x, y) {
    console.log(x);
    console.log(y);
}

var data = {
    "property": {
        "1": {
            "values": [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
        },
        "2": {
            "values": [[11, 12], [13, 14], [15, 16], [17, 18], [19, 20]]
        }
    }
}

var delay = 1000;

for (var x in data.property) {
    for (var i = 0; i < data.property[x].values.length; i++) {
        var one  = data.property[x].values[i][0];
        var two  = data.property[x].values[i][1];

        setTimeout(function() {
            write(one, two);
        }, delay);

        delay += 1000;
    }
}

从对象读取数据并在对象和其中的数组上循环。我希望它相隔一秒打印数组值,但它总是打印最后一次迭代的值。我已尝试使用其他问题中建议的闭包,但无法使其工作。

3 个答案:

答案 0 :(得分:1)

您可以应用own research并使用以下方法。

for (var i = 0; i < data.property[x].values.length; i++) {
    (function (one, two) {
        setTimeout(function() {
            write(one, two);
        }, delay);
    })(data.property[x].values[i][0], data.property[x].values[i][1]);

    delay += 1000;
}

工作jsfiddle:http://jsfiddle.net/0z525bhf/1/

答案 1 :(得分:1)

setTimeout的特定情况下,您甚至不需要关闭。您可以将变量传递给超时函数,如下所示:

for (var x in data.property) {
    for (var i = 0; i < data.property[x].values.length; i++) {
        var one  = data.property[x].values[i][0];
        var two  = data.property[x].values[i][1];

        setTimeout(function(one, two) {
            write(one, two);
        }, delay, one, two);

        delay += 1000;
    }
}

答案 2 :(得分:0)

这是词汇闭包的问题:传递给setTimeout的函数会关闭在迭代期间被修改的变量onetwo。这就是为什么你应该永远不要在for循环体中声明一个函数。

使用功能循环将解决它:

var delay = 1000;
for (var x in data.property) {
  data.property.value[x].forEach(function (tuple) {
    var one = tuple[0], two = tuple[1];
    setTimeout(function() {
      write(one, two);
    }, delay);
    delay += 1000;
  });
}