的JavaScript变量作用域[重复](JavaScript Variable Scope [du

2019-08-19 08:49发布

这个问题已经在这里有一个答案:

  • JavaScript的闭包内环路-简单实用的例子 43个回答

我有一些JavaScript代码的问题。

脚本

setTimeout(function() {
    for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, i * 200);
    }
}, 200);

输出

5,5,5,5,而不是5 1,2,3,4,5

我可以种明白为什么这是行不通的,但我想知道如果有人能向我解释发生了什么,为什么它不工作!

此外,这怎么能范围的问题被克服?

Answer 1:

setTimeout回调函数是异步执行的,所有console.log叫你做参考同i的变量,并在它们被执行时,for循环已经结束i有4个。

你可以换你内心setTimeout接受一个参数,以便将其存储到所有的引用的函数调用里面i正在重复的值,这样的事情:

setTimeout(function() {
    for (var i = 0; i < 5; i++) {
      (function (j) { // added a closure to store a reference to 'i' values
        setTimeout(function() {
            console.log(j);
        }, j * 200);
      })(i); // automatically call the function and pass the value
    }
}, 200);

检查我的回答更多细节以下问题:

  • 在匿名函数的变量-谁能解释下?


Answer 2:

看看这个问题 。 它可以帮助你理解范围和封闭好,非常相似,你的问题。



Answer 3:

你想创建一个包含变量“i”的封闭。 但封闭在一个函数结束时才创建。 因此,如果在创建for循环的功能,它们将不得不从最后一次迭代的值。

你可以用这样的修正:

var createFunction = function(index) {
  return function() {
    console.log(index);
  }
};

for (var i = 0; i < 5; i++) {
  setTimeout(createFunction(i), i * 200);
}

在那里你从另一个函数返回的功能。



Answer 4:

可变i存在于外部函数的范围。

它改变的循环运行。

内部函数引用它。

尝试是这样的:

var i_print_factory = function (value) {
  return function () {
    console.log(value);
  };
};

var init_timers = function () {
  for (var i = 0; i < 5; i++) {
    setTimeout(i_print_factory(i), i * 200);
  }
};

setTimeout(init_timers, 200);


Answer 5:

因为你正在访问同一个变量i在设定的超时用到的所有功能。 setTimeout函数集火的毫秒数在今后的同一个线程中变量i的功能。 I值并不在函数复制功能所引用的实际变量i,当它被激发。 因为你已经通过父函数循环,直到I = 5和之前其他任何有机会火做到这一点,他们都显示为5。



文章来源: JavaScript Variable Scope [duplicate]