var / let / const 区别
解释 JavaScript 中 var、let、const 在作用域、变量提升、暂时性死区和重新赋值方面的核心差异。
#tech / dev / frontend
#type / concept
#status / growing
#resource / javascript
#resource / ecmascript
[!info] related notes
- 所属 MOC: ECMAScript MOC, ES6 新特性 MOC, 前端基础 MOC
- 前置概念: 变量提升
- 并列概念: ECMAScript 闭包, ECMAScript 执行上下文
- 面试问法: Event Loop、宏任务和微任务怎么理解
var / let / const 区别
这篇笔记回答一个问题:var、let、const 在 JavaScript 中到底差在哪。
一句话定义
var 是函数作用域且存在变量提升,let 和 const 是块级作用域且存在暂时性死区,const 额外要求不能重新绑定。
核心差异
| 维度 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | 是(初始值为 undefined) | 是(但进入暂时性死区) | 是(但进入暂时性死区) |
| 暂时性死区 | 无 | 有 | 有 |
| 重新赋值 | 允许 | 允许 | 不允许 |
| 重复声明 | 允许 | 不允许 | 不允许 |
核心机制
变量提升
var 声明会在编译阶段被提升到函数顶部,未赋值前访问得到 undefined。
console.log(a); // undefined
var a = 1;
let / const 也会提升,但进入”暂时性死区”(TDZ),声明前访问会抛 ReferenceError。
console.log(b); // ReferenceError
let b = 1;
暂时性死区
从块开始到 let / const 声明语句之间的区域称为暂时性死区。这段时间内变量已存在但不能访问。
if (true) {
// TDZ 开始
console.log(x); // ReferenceError
let x = 1; // TDZ 结束
}
块级作用域
let / const 只在最近的 {} 内有效,var 会逃逸到函数级别。
for (var i = 0; i < 3; i++) {}
console.log(i); // 3,var 逃逸
for (let j = 0; j < 3; j++) {}
console.log(j); // ReferenceError,let 不逃逸
const 的不可重新绑定
const 不允许改变绑定本身,但如果值是对象或数组,内部属性仍可修改。
const obj = { a: 1 };
obj.a = 2; // 可以
obj = {}; // TypeError: 不能重新赋值
常见误解
- “let / const 不会提升” -> 错误,它们会提升,只是进入 TDZ
- “const 声明的值完全不可变” -> 错误,只是绑定不可变,对象属性可变
- “var 只有全局和函数两个作用域” -> 正确,没有块级作用域
最小例子
// var: 函数作用域,提升为 undefined
function testVar() {
console.log(x); // undefined
var x = 1;
}
// let: 块级作用域,TDZ
function testLet() {
// console.log(y); // ReferenceError
let y = 1;
}
// const: 块级作用域,不可重绑
function testConst() {
const z = 1;
// z = 2; // TypeError
}