在Javascript中解释闭包的输出

时间:2017-01-25 11:26:11

标签: javascript

在下面的代码片段中,6次打印5次。 请解释一下这种输出行为。

至于每个我,我正在调用settimeout函数,所以console.log应该具有i的值。 代码:

for(var i = 1;i <= 5;i++) {
   setTimeout(function() {
      console.log("i:" +  i);
   },i*1000);
}

O / P 6 6 6 6 6

O / P意图 1 2 3 4 5

4 个答案:

答案 0 :(得分:2)

即使超时0也会产生相同的结果。要理解这一点,你必须从事件循环的角度理解回调的概念。理想情况下,只有当堆栈为空时才执行回调,js代码执行是基于堆栈的我的意思是执行上下文所以当你在这里说一个for循环时它意味着第一个i被推入堆栈所以现在堆栈处理变量及其增量值它存储的回调(setTimeout)是一个事件循环。

在事件循环中运行块的唯一方法是当堆栈为空时,即当循环结束时,它的闭包函数保留了打印所有日志的最后一个值。

参见示例,您将看到1到6个回调外部,因为它在堆栈中执行,但仅在堆栈为空时才进行回调。

如果您想最好地理解执行上下文,请转到https://maps.googleapis.com/maps/api/geocode/json?address=5989%20Route%206N%20Edinboro%20Pennsylvania%20United%20States%2016412并复制粘贴您的js代码以查看操作。

&#13;
&#13;
for(var i = 1;i <= 5;i++)
    {
        console.log(i)
        setTimeout(function(){
                console.log("i:" +  i);
                     },0
               );

    }
&#13;
&#13;
&#13;

答案 1 :(得分:1)

因为该函数使用for循环的相同范围内的变量

执行setTimeout函数时,范围中的变量i已更改值,因此所有计时器都将打印循环的最后一个值

尝试将i值作为setTimeout的参数传递,以便立即对其进行求值,并且函数可以在其自己的范围内使用值,没有任何副作用播放技巧

for(var i = 1;i <= 5;i++)
    {
        setTimeout(function(a){
                console.log("i:" +  a);
                     },i*1000,i
               );

    }

答案 2 :(得分:0)

在js中,变量具有块/函数作用域,并且setTimeout也是异步工作。

答案 3 :(得分:0)

由于setTimeout是异步的,因此for循环将在调用sitetimeOut函数之前运行。 for循环的最后一次迭代将i设置为6。因此,一旦设置的timeOut函数在for循环之后运行,它将打印出6。