6

该代码存在一个问题,即在调用异步函数时变量会被覆盖。如何修复?

代码:

for (x in files) {

 asynchronousFunction(var1, var2, function(){
      console.log(x.someVaraible);
  }); 

}

现在的问题是,当调用 asynchronousFunction 中的回调函数时,x.files 变量已更新为 json 数组文件中的下一个变量。我希望变量应该包含以前的值。

回调函数中的变量个数不能改变,所以不能在回调函数中发送变量名。

4

4 回答 4

13

在 javascript 中使用“本地”变量的问题在于您的变量实际上具有函数范围,而不是块范围 - 就像 Java 和 C# 等一样。

解决此问题的一种方法是使用letwhich has block scope,但目前只有 firefox 支持。

所以这段代码只能在 Firefox 中工作:

for (var x in files) {
  // This variable has BLOCK scope
  let file = files[x];
  asynchronousFunction(var1, var2, function(){
     console.log(file.someVariable);
  }); 
}

对于其他浏览器,替代方法是使用闭包

for (var x in files) {
  var file = files[x];
  asynchronousFunction(var1, var2, (function(file){
      return function() {
                console.log(file.someVariable);
             };
  })(file); 
}

另一种方法是使用 map/forEach,假设文件的数据类型是数组。

files.forEach(function(file) {
     asynchronousFunction(var1, var2, function(){
                console.log(file.someVariable);
             });
});

如果它不是一个数组,那么你总是可以使用这种技术

 [].forEach.call(files, function(file) {
     asynchronousFunction(var1, var2, function(){
                console.log(file.someVariable);
             });
});

更完整的写法当然是

Array.prototype.forEach.call(files, function(file) {
     // As before

但我觉得[].forEach眼睛更好看。

于 2012-07-31T19:13:37.457 回答
1

您需要x从回调函数创建的闭包中分离出来。简短的回答:

for (x in files) {
    asynchronousFunction(var1, var2,
        (function(y){
            return function(){
                console.log(y.someVaraible);
            }
        })(x)
    ); 
}

有关更长的答案和解释,请参阅我对上一个问题的回答:请解释在循环中使用 JavaScript 闭包

于 2012-07-31T19:11:00.840 回答
0

您需要将变量绑定到函数定义,或者将变量传递给函数。我可能会采取组合方法,例如:

for (x in files) {
    var local_x = x;
    var fn = function () {
         theRealFunction( local_x );
    };
    asynchronousFunction(var1, var2, fn);
}

尽管在您的示例中,我不需要调用 theRealFunction(),因为它的代码量很少(只是 console.log)。

于 2012-07-31T19:07:12.913 回答
0

X 被迭代,所以在调用回调函数时,x 将是循环中的最后一个迭代函数。

通过像这样进行x本地修复:

for (x in files) {
    (function() {
        var x = arguments[0];
        asynchronousFunction(var1, var2, function() {
            console.log(x.someVaraible);
        });
    }(x));
}
于 2012-07-31T19:08:18.160 回答