为何使用var时循环输出11,而let可实现正常遍历输出?
为什么用
var声明循环变量会全输出11,用let却能正常输出0到10? 先看你给出的这段代码:
var functions = []; for (var x = 0; x <= 10; x++) { functions.push(function() { console.log(x); }); } functions.forEach( function(func) { func(); } );
用var时的核心问题:共享同一个变量引用
用var声明的x是函数级作用域(如果这段代码不在函数内部,那就是全局作用域),整个循环过程中只有这一个x变量存在。你每次往数组里添加的函数,并没有“保存”当前循环的x值,而是记住了x这个变量本身的引用。
等循环结束时,x已经自增到11了(最后一次循环x=10满足条件,执行完循环体后x++变成11,此时不满足x<=10,循环停止)。当你后续调用数组里的函数时,它们都会去取这个已经变成11的x,所以自然全输出11。
用let时的关键差异:每次循环创建独立变量
let是块级作用域,而且在for循环里有个特殊的设计:每一轮循环迭代时,都会创建一个全新的x变量,这个变量只属于当前这一轮循环的块作用域。
也就是说,你每一次添加到数组里的函数,引用的都是当前循环独有的那个x,它的值就是当前迭代的数值(0、1、2...10)。等循环结束后,每个函数各自持有自己那一轮的x引用,调用时就会依次输出0到10。
额外补充:用var模拟let的效果
如果想用var实现和let一样的结果,可以手动用立即执行函数(IIFE)创建独立作用域:
var functions = []; for (var x = 0; x <= 10; x++) { (function(currentX) { functions.push(function() { console.log(currentX); }); })(x); } functions.forEach( function(func) { func(); } );
这里每次循环都把当前的x值传给立即执行函数的参数currentX,这个currentX是函数内部的局部变量,每个数组里的函数都引用着自己对应的currentX,所以也能正常输出0到10。而let相当于帮你自动完成了这个“创建独立变量”的工作,不用手动写IIFE了。
内容的提问来源于stack exchange,提问作者Rene Israel Ibarra
相关产品推荐
相关产品推荐

