一道经典面试题:let 和 var 在for循环中的不同

427 阅读1分钟
let array = [];
for (let i = 0; i < 10; i++) {
    array[i] = function () {
        console.log(i);
    }}array[6]();
// 6
let array2 = [];
for (var j = 0; j < 10; ++j) {
    array2[j] = function () {
        console.log(j);
    }}
array2[6]();
// 10

let是块级作用域,每次循环都会产生新的块级作用域,每个块级作用域的i是独立的,i并不相同。执行array[6]中的i和array[0]中的i并不是同一个块级作用域的i。

var是函数作用域,j和array2是同级的,j在for循环中一直有效,每次循环j都会增加1,循环结束后j变为10。而循环体内的function定义后并不会立即执行,执行时会在全局作用域上找到j,此时j为10。

如何使var定义的函数array2[6]也能打印出6呢?

for (var j = 0; j < 10; ++j) {
    array2[j] = (function (j) {
        return function(){ 
           console.log(j)
        }
    })(j)
};
array2[6]();

// 6

执行代码,我们可以清晰地看到:j被标记为(Closure)闭包变量。

函数执行完毕,上下文被销毁,但是在函数中,我们返回了一个函数。且这个函数我们使用了(外层)函数内的j变量,因此在(外层)函数执行完毕出栈后,j不会消失,仍有机会被外界访问到。