😕
循环中的函数
之前,只是知道 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);
})
}
in
和 of
循环也是一样的
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-in
和 for-of
,const
的使用效果与 let
一致, 只是不能在循环内手动修改迭代的值。
let arr2 = [[1, 3], [2, 4]];
for (const i of arr2) {
console.log(i);
// i = [0]; // TypeError: Assignment to constant variable.
}
之所以可以这样,原因同前面的 let 一样,在 for-in
和 for-of
时,会创建一个新的 const 绑定。
相当于将值进行了复制,每次迭代时都从 arr2
中取出值赋值给迭代变量。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。