为什么存储的函数会引用更新后的全局变量i的值,输出3而非2?
var printNumTwo; for (var i = 0; i < 3; i++) { if (i === 2) { printNumTwo = function() { return i; }; } } console.log(printNumTwo());
原因说明
- 首先
var声明的变量不存在块级作用域,上述代码中i是全局作用域下的唯一变量,整个for循环迭代过程中复用的都是同一个i。 - for循环的终止条件是
i < 3不成立,当循环执行完毕时,i的最终值为3。 - 你赋值给
printNumTwo的函数是一个闭包,它捕获的是i变量的引用,而非赋值那一刻i的快照值。等到你调用printNumTwo()时,for循环已经完全执行结束,此时读取到的i就是最终的3。
修复方案
如果想要得到预期的2,可以用以下两种常见方案:
- 把
var i改成let i:let支持块级作用域,for循环每次迭代都会生成一个独立的i变量,闭包会捕获对应迭代批次的i值:
var printNumTwo; for (let i = 0; i < 3; i++) { if (i === 2) { printNumTwo = function() { return i; }; } } console.log(printNumTwo()); // 输出2
- 使用立即执行函数(IIFE)在赋值时锁定当前i的值:
var printNumTwo; for (var i = 0; i < 3; i++) { if (i === 2) { printNumTwo = (function(i) { return function() { return i; } })(i) } } console.log(printNumTwo()); // 输出2
内容的提问来源于stack exchange,提问作者adhi
相关产品推荐
相关产品推荐

