ar / let / const 以及不同写法的区别一
1. let
在 for 里(常见)
for (let i = 0; i < 3; i++) { console.log('loop:', i); } console.log(i); // ❌ ReferenceError: i is not defined
原因:let
是 块级作用域,i
只存在于 for 的大括号里。循环结束自动销毁。
2. var
在 for 里
for (var i = 0; i < 3; i++) { console.log('loop:', i); } console.log(i); // ✅ 3
原因:var
是 函数作用域,在函数外就是全局作用域,循环结束变量依旧存在。
3. 提前声明 let
let i; for (i = 0; i < 3; i++) { console.log('loop:', i); } console.log(i); // ✅ 3
原因:i
在外层作用域声明,所以循环结束后还可以访问。
4. const
在 for 里(❌ 会报错)
for (const i = 0; i < 3; i++) { console.log(i); } // ❌ TypeError: Assignment to constant variable.
原因:const
不能重新赋值,for 循环的迭代 i++
会修改它,所以报错。
5. const
在 for...of 或 for...in 里(✅ 可用)
for (const item of [1, 2, 3]) { console.log(item); } console.log(item); // ❌ ReferenceError
原因:每一次循环 item
都是新的常量,允许重复声明,但只能在循环内部访问。
6. for 循环里的异步 + var
(坑点)
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // 输出:3 3 3
原因:var
没有块级作用域,所有回调里的 i
共享一个变量,循环结束 i=3。
7. for 循环里的异步 + let
(推荐)
for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // 输出:0 1 2
原因:let
会为每次循环创建一个独立作用域,保存当前 i
的值。
8. for 循环里 let
结合解构
for (let [index, value] of ['a', 'b'].entries()) { console.log(index, value); } // 输出:0 'a' 1 'b'
原因:let
可以在每次循环独立绑定多个变量。
💡 总结表
关键字 | 作用域类型 | 循环结束后能访问? | 异步闭包表现 |
---|---|---|---|
var | 函数作用域 | ✅ 能 | 所有回调用同一个值 |
let | 块级作用域 | ❌ 不能(除非外层声明) | 每次循环独立保存值 |
const | 块级作用域 + 常量 | ❌ 不能(除非外层声明) | 每次循环新常量 |