当我在另一个函数中使用setTimeout并尝试打印传递的参数值时,究竟发生了什么?

时间:2016-09-14 11:18:55

标签: node.js asynchronous

当我不得不完成杂耍的异步挑战时,我正在经历learnyounode,这就是我遇到类似的简单问题,如下所示:

// try print numbers 0 - 9
for (var i = 0; i < 10; i++) {
  setTimeout(function() {
    console.log(i)
  })
}

上面的代码段将输出显示为:

10
10
10
10
10
10
10
10
10
10

这不是预期的结果,但是当我按照以下方式编写它时:

// try print numbers 0 - 9
var f = function(i) {
  setTimeout(function() {
    console.log(i)
  })
}
for (var i = 0; i < 10; i++)f(i);

我得到了所需的输出。那么当我在该函数中编写setTimeout()部分时究竟发生了什么呢?

2 个答案:

答案 0 :(得分:2)

在第一个剪切中, i 变量在函数外部定义。你可以只是因为它在(更高级别)范围内而且在函数自己中没有定义另一个 i 变量(或任何中间的,如果存在的话),就可以访问它。

for循环设置十次超时(排队到事件循环)。但它们只会在for循环结束时执行,因此 i 值为10(迭代的最后一个)。

在第二个例子中,你围绕一个闭包(函数)中的setTimeout(),它在每个循环迭代中执行立即

在这些迭代中,当调用函数时,i的当前值作为参数传递(也称为i,在本地函数的范围中定义为 ,因为它具有相同的名称,隐藏你没有调用相同变量的事实。)

请参阅下面第二个示例的略微修改:

// try print numbers 0 - 9
var f = function(j) {
  setTimeout(function() {
    console.log(i, j)
  })
}
for (var i = 0; i < 10; i++)f(i);

// Output:
// -------
// 10 0
// 10 1
// 10 2
// 10 3
// 10 4
// 10 5
// 10 6
// 10 7
// 10 8
// 10 9

答案 1 :(得分:1)

这是因为用var声明的变量是函数级的,而不是块级的。

第一个snippt是下面相同的代码 ```

var i;
// try print numbers 0 - 9
for (i = 0; i < 10; i++) {
  setTimeout(function() {
    console.log(i)
  })
}

所有&#39;我指向内存中相同的地址,最终等于10。

当涉及到第二个snippt时,因为你将i作为参数传递给一个函数,i的实际值将复制到该函数的堆栈中的新内存地址。函数中的每个i都指向具有不同值的新内存地址。