var / let / const 全面对比
核心区别总结
| 特性 |
var |
let |
const |
| 作用域 |
函数作用域 |
块级作用域 |
块级作用域 |
| 变量提升 |
提升并初始化undefined |
提升但不初始化(TDZ) |
提升但不初始化(TDZ) |
| 重复声明 |
允许 |
禁止 |
禁止 |
| 全局绑定 |
成为window属性 |
不成为window属性 |
不成为window属性 |
| 初始值 |
可不初始化 |
可不初始化 |
必须初始化 |
| 循环中的表现 |
每次循环共享同一变量 |
每次迭代创建新绑定 |
每次迭代创建新绑定 |
关键概念详解
1. 块级作用域(Block Scope)
let和const声明的变量只在代码块{}内有效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { var a = 1; let b = 2; const c = 3; } console.log(a); console.log(b); console.log(c);
**典型应用**:
```javascript // 解决循环变量泄露 for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i)); // 0,1,2(正确) } for (var j = 0; j < 3; j++) { setTimeout(() => console.log(j)); // 3,3,3(泄露到全局) }
|
2. 暂时性死区(TDZ - Temporal Dead Zone)
在声明前访问let/const变量会触发错误(而var返回undefined):
1 2 3 4 5
| console.log(a); var a = 10;
console.log(b); let b = 20;
|
TDZ 本质:
从进入作用域到变量声明之间的区域,禁止访问变量
3. const 的特殊行为
1 2 3 4 5 6
| const a = {}; a.x = 1; a = {};
const b = Object.freeze({}); b.x = 1;
|
const 本质:
- 保证变量指向的内存地址不变(对于对象是堆地址,对于基本类型是栈值)
- 对象属性修改不受限制(除非使用
Object.freeze)
最佳实践指南
**默认使用 const**
除非需要重新赋值,否则优先用const(减少意外修改)
1 2
| const API_URL = "https://api.example.com"; const config = { timeout: 5000 };
|
**需要重新赋值时用 let**
替代var的所有场景
1 2
| let count = 0; count = processItems(items);
|
**避免使用 var**
除特殊兼容场景外不应使用
const 对象保护技巧
1 2 3 4 5 6 7 8 9 10
| const deepFreeze = obj => { Object.freeze(obj); Object.keys(obj).forEach(key => { if (typeof obj[key] === 'object') deepFreeze(obj[key]); }); };
const safeObj = deepFreeze({ nested: { value: 1 } }); safeObj.nested.value = 2;
|
常见误区
1 2 3 4 5 6 7 8 9 10 11 12 13
| const user = { name: "Alice" }; user.name = "Bob";
for (const i = 0; i < 3; i++) { console.log(i); }
for (const item of [1,2,3]) { console.log(item); }
|
浏览器兼容性
let/const:ES6+(现代浏览器全支持,IE11部分支持)
- 旧环境需通过Babel转译为ES5