首页 > 解决方案 > 为什么 Javascript 以这种方式工作?

问题描述

所以我在推特上看到了某人的推文,提到下面的脚本是在面试时给出的。

for (var i = 0; i < 3; i+=1) {
    setTimeout(function() {
        console.log(i)
    }, 100)
}

受访者被要求预测这个剧本的结果,他在推文中提到这对他来说是显而易见的。

对我来说,作为对 Javascript 的全新(或不感兴趣),很难理解为什么结果不是:

1) 0、1、2 顺序。(作为传统的'for-loop')

2)。3 只打印一次。(如果在调用函数之前迭代完全完成)

但打印 3 三遍。

这是因为 Javascript 不是顺序编程语言,或者 Javascript 的特性,还是两者兼而有之?

标签: javascriptfunctional-programming

解决方案


要理解这一点,您需要了解 JavaScript 如何基于事件以及范围如何工作,这就是为什么我认为它被用作面试问题的原因。

基本上,JavaScript 是基于事件队列的。在提供的示例代码中,setTimeout不会立即执行代码,而是让引擎知道代码应该在 100 毫秒内触发。

但是,for循环会立即执行。如果您使用块范围的变量定义,这本身不会有问题,例如let i = 0. 例如,以下代码将打印 0、1、2:

for (let i = 0; i < 3; i+=1) {
    setTimeout(function() {
        console.log(i)
    }, 100)
}

但是,在代码var中使用,它被“提升”到函数定义的顶部,或者在这种情况下,是片段/文件的顶部。所以实际上,代码在引擎看来如下所示:

var i;
for (i = 0; i < 3; i+=1) {
    setTimeout(function() {
        console.log(i)
    }, 100)
}

这有一个有趣的效果:现在 for 循环运行了 3 次,增加到ivalue 3然后在 for 循环完成执行后,setTimeout回调函数被调用,它i在其范围内具有相同的值(因为它被提升了)。这就是它打印 3 三次的原因。


推荐阅读