【问题标题】:JS: setTimeout always prints values from last iteration [duplicate]JS:setTimeout 总是打印上一次迭代的值[重复]
【发布时间】:2014-08-12 11:27:01
【问题描述】:

我知道这个问题与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;
    }
}

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

【问题讨论】:

    标签: javascript arrays loops object


    【解决方案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】:

    您可以申请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/

    【讨论】:

      【解决方案3】:

      这是词法闭包的问题:传递给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;
        });
      }
      

      【讨论】:

      • 感谢您的解释。我不得不在一个地方编辑它,这里是所提供示例的工作版本:jsfiddle.net/qdstdyrh
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-30
      • 2016-03-07
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多