跳到主要内容

let 有什么用,有了 var 为什么还要用 let?

面试速答(30 秒版 TL;DR)

  • let 提供块级作用域,解决 var 的函数作用域带来的变量泄漏、循环异步捕获等问题。
  • let暂时性死区(TDZ),能更早暴露“先用后声明”的错误。
  • let 不允许同一作用域重复声明,降低隐式覆盖风险。

核心差异对比(面试高频)

  • 作用域:
    • var:函数作用域(或全局作用域),没有块级作用域。
    • let:块级作用域({}forifswitch 等)。
  • 提升(hoist)与初始化:
    • var:声明提升并初始化为 undefined,容易“看起来能用”但逻辑错误。
    • let:声明也会被“登记”,但在声明语句执行前处于 TDZ,访问会抛错。
  • 重复声明:
    • var:允许重复 var x
    • let:同一作用域重复声明直接报错。

经典题:for 循环 + 异步输出

for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 常见输出:3 3 3

改成 let

for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 0 1 2

可讲清楚的点:letfor 中会为每次迭代创建新的绑定,因此闭包捕获到的是“每次迭代各自的 i”。


暂时性死区(TDZ)是为了什么?

console.log(x); // ReferenceError
let x = 1;

TDZ 的价值:让“先用后声明”更快失败,避免 var 那种默默得到 undefined 的隐性 bug。


常见追问

Q:那我用 const 不就好了?

  • const 也有块级作用域和 TDZ,但它强调“绑定不可重新赋值”。
  • 需要重新赋值的场景用 let,不需要重新赋值用 const(更利于阅读与约束)。

易错点/坑

  • let 没有提升”是口误:更准确说法是“有提升的登记,但在声明前不可访问(TDZ)”。
  • let 的块级作用域会影响某些老代码的重构方式,尤其是依赖变量泄漏的写法。

速记要点(可背诵)

  • let:块级作用域 + TDZ + 禁止重复声明,主要用来修复 var 的坑。