Tec*_*ast 1 javascript functional-programming
所以我在 Twitter 上看到了某人的推文,提到以下脚本是在求职面试中给出的。
for (var i = 0; i < 3; i+=1) {
setTimeout(function() {
console.log(i)
}, 100)
}
Run Code Online (Sandbox Code Playgroud)
受访者被要求预测这个剧本的结果,他在推文中提到这对他来说很明显。
对我来说,作为对 Javascript 的全新(或不感兴趣),很难理解为什么结果不是:
1) 0, 1, 2 依次。(作为传统的'for-loop')
2)。只打印 3 一次。(如果在调用函数之前完全完成了迭代)
但是打印 3 三遍。
这是因为 Javascript 不是顺序编程语言,或者 Javascript 的特征,或者两者兼而有之?
要理解这一点,您需要了解 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)
}
Run Code Online (Sandbox Code Playgroud)
但是,在代码var中使用,它被“提升”到函数定义的顶部,或者在这种情况下,代码段/文件的顶部。所以实际上,代码在引擎中看起来如下:
var i;
for (i = 0; i < 3; i+=1) {
setTimeout(function() {
console.log(i)
}, 100)
}
Run Code Online (Sandbox Code Playgroud)
这有一个有趣的效果:现在 for 循环运行了 3 次,增加到ivalue 3。然后在 for 循环执行完毕后,setTimeout回调函数被调用,它i在其范围内具有相同的值(因为它被提升)。这就是为什么它会打印 3 次 3 次。