【问题标题】:How come setitimeout function is access value of i even after the function call is over即使在函数调用结束后,settimeout 函数为什么是 i 的访问值
【发布时间】:2020-05-06 08:24:56
【问题描述】:

function printSeries() {
	for (var i = 0; i < 10; i++) {
		setTimeout(function () {
			console.log(i);
		}, 3000);
	}
	console.log('printing');
}

printSeries();

为什么打印值是 i 的 10 倍?堆栈为空后调用 SetTimeout 回调函数。它是否在其中存储了词法范围

【问题讨论】:

  • 您的每次执行都将超时,因此 3 秒后全部打印,这就是它的方式。它不会取消它等待执行的执行

标签: javascript settimeout


【解决方案1】:

当脚本第一次到达setTimeout 时,它会将您的函数添加到队列中以在 3 秒后执行,然后立即继续循环。

到 3 秒过去时,循环已经完成了很长时间(一个简单循环的 10 次迭代不需要 3 秒),这就是为什么您可以这么早就看到 'printing' 消息的原因。

此时i10,所以10被打印了10次(因为这是函数被加入队列的次数。Javascript使用i的当前值,而不是函数第一次添加到队列时i 的值。

这是脚本的修改版本,它在将函数添加到队列时使用了i 的值:

function printSeries() {
  for (var i = 0; i < 10; i++) {

    setTimeout((function(i) {
      return function() {
        console.log(i);
      }
    }(i)), 3000);

  }
  console.log('printing');
}

printSeries();

这里,i 的值绑定到函数,而不仅仅是引用。

【讨论】:

  • 感谢您的回答,无论是在您的修订版中打印十次 10 还是 0 -9,我都很好。我们知道 setTimeout 回调会在堆栈变空后从事件队列中获取。我的问题是 var 是函数级别范围,如果函数已经完成,那么 setTimeout 函数如何访问 i 的值。它是否有关于 settimeout 的创建位置的上下文参考或有其他一些概念。
  • setTimeout 在函数内部被调用,因此它可以访问函数的范围。函数内部的循环是否结束并不重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-15
  • 2020-08-22
  • 1970-01-01
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-22
相关资源
最近更新 更多