var、let、const 的区别
What is the difference between var, let and const
一句话:var 是函数作用域、会提升成undefined、能重复声明;let / const 是块作用域、 有 TDZ、不能重复声明;const 还不能重新赋值。
var | let | const | |
|---|---|---|---|
| 作用域 | 函数 | 块 {} | 块 |
| 声明前访问 | undefined | 报 ReferenceError | 报 ReferenceError |
| 重复声明 | 可以 | 不行 | 不行 |
| 重新赋值 | 可以 | 可以 | 不行 |
挂到 window | 顶层会挂 | 不挂 | 不挂 |
TDZ(暂时性死区)是let / const「从块开始到声明那一行」之间的区域。 变量确实被提升了,但被标记为「还不能用」, 所以访问会抛错而不是给 undefined。 这是刻意设计的 —— 让错误早暴露。
会追问:「const 的对象能改属性吗?」——能。const 锁的是绑定(这个名字不能再指向别的东西), 不是值。 想冻结内容用 Object.freeze()。
还会追问循环那道经典题——for (var i…) 配setTimeout 会打出三个 3,let 会打出 0 1 2。 因为 let每次迭代都创建一个新的绑定, 而 var 全程只有一个 i。 这题和闭包(#298)连着考。
In one line: var is function-scoped, hoists to undefined and can be redeclared; let / const are block-scoped, have a TDZ and cannot be redeclared; const on top of that cannot be reassigned.
var | let | const | |
|---|---|---|---|
| Scope | Function | Block {} | Block |
| Read before the declaration | undefined | throws ReferenceError | throws ReferenceError |
| Redeclare | Allowed | No | No |
| Reassign | Allowed | Allowed | No |
Lands on window | Yes at top level | No | No |
The TDZ (temporal dead zone) is the stretch between the start of the block and the let / const line itself. The variable really is hoisted, but flagged as “not usable yet”, so reading it throws instead of handing you undefined. That is deliberate — it makes mistakes surface early.
Follow-up: “Can you change the properties of a const object?” — yes. const locks the binding (the name cannot point at anything else), not the value. To freeze the contents, use Object.freeze().
Another follow-up — the classic loop question: for (var i…) with setTimeout prints three 3s; let prints 0 1 2. Because let creates a fresh binding on every iteration, while var has one single i the whole way through. This gets asked together with closures (#298).