循环中的作用域

  1. 循环中的函数
  2. 循环中的 let 声明:
  3. 循环中的 const 声明

😕

循环中的函数

之前,只是知道 let 的块作用域和 var 的函数作用域,今天看了看书,发现自己的理解其实有偏差。
记住下面这句话:

let 声明在循环内部的行为是 ES 标准中专门定义的,与 let 的变量提升没有直接关联。

看代码:

var funcs = [];

for (var i = 0; i <= 10; i++) {
    funcs.push(function () {
        console.log(i);
    })
}

funcs.forEach(function (ele) {
    ele();
})

结果为,输出打印 10 个 11。
因为调用函数时,打印的 i 指向的都是一个 i
不想使用那个变量 i
可以使用 IIFE - 立即执行函数, 强制生成 变量 i 的一个副本。
看代码:

for (var i = 0; i <= 10; i++) {
    (function (i) {
        funcs.push(function () {
            console.log(i);
        });
    })(i)
}
// 也是 IIFE
for (var i = 0; i <= 10; i++) {
    funcs.push(
        (function (value) {
            return function () {
                console.log(value);
            }
        })(i)
    );
}

IIFE 表达式为自己接收的 每一个变量 i 都创建了一个 ** 副本 **。这个副本的值显然就是此时的变量 i 的值。

循环中的 let 声明:

每次循环, let 声明创建一个 新变量 i, 将其初始化 i 的当前值, 所以, 循环内部创建的函数都得到了 i 的副本。

// 输出 0-10
for (let i = 0; i <= 10; i++) {
    funcs.push(function () {
        console.log(i);
    })
}

inof 循环也是一样的

let funcs = [];
let arr = ['a', 'v', 'e', 'd'];

// for (var e of arr) {
//     funcs.push(function () {
//         console.log(e);
//     })
// } // d d d d

// for (let e of arr) {
//     funcs.push(function () {
//         console.log(e);
//     })
// }// a v e d

// for (var e in arr) {
//     funcs.push(function () {
//         console.log(e);
//     })
// } // 3 3 3 3

// for (let e in arr) {
//     funcs.push(function () {
//         console.log(e);
//     })
// } // 0 1 2 3

funcs.forEach((e) => {
    e();
})

循环中的 const 声明

由于 const 声明的基本类型是不可变的,所以下面的代码报错:

for (const i = 0; i < 9; i++) {
    console.log(i);
}

具体是指 i++ 时 TypeError: Assignment to constant variable.
对于 for-infor-ofconst 的使用效果与 let 一致, 只是不能在循环内手动修改迭代的值。

let arr2 = [[1, 3], [2, 4]];
for (const i of arr2) {
    console.log(i);
    // i = [0]; // TypeError: Assignment to constant variable.
}

之所以可以这样,原因同前面的 let 一样,在 for-infor-of 时,会创建一个新的 const 绑定。
相当于将值进行了复制,每次迭代时都从 arr2 中取出值赋值给迭代变量。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。
我的空间