003-var-let-const 全面对比

var / let / const 全面对比

核心区别总结

特性 var let const
作用域 函数作用域 块级作用域 块级作用域
变量提升 提升并初始化undefined 提升但不初始化(TDZ) 提升但不初始化(TDZ)
重复声明 允许 禁止 禁止
全局绑定 成为window属性 不成为window属性 不成为window属性
初始值 可不初始化 可不初始化 必须初始化
循环中的表现 每次循环共享同一变量 每次迭代创建新绑定 每次迭代创建新绑定

关键概念详解

1. 块级作用域(Block Scope)

letconst声明的变量只在代码块{}内有效:

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); // 1(var穿透块作用域)
console.log(b); // ReferenceError
console.log(c); // ReferenceError


**典型应用**:

```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); // undefined(变量提升)
var a = 10;

console.log(b); // ReferenceError(TDZ区域)
let b = 20;

TDZ 本质
从进入作用域到变量声明之间的区域,禁止访问变量

3. const 的特殊行为

1
2
3
4
5
6
const a = {};
a.x = 1; // ✅ 允许(修改对象内部属性)
a = {}; // ❌ TypeError(禁止重新赋值)

const b = Object.freeze({});
b.x = 1; // ❌ 静默失败(严格模式报错)

const 本质

  • 保证变量指向的内存地址不变(对于对象是堆地址,对于基本类型是栈值)
  • 对象属性修改不受限制(除非使用Object.freeze

最佳实践指南

  1. **默认使用 const**
    除非需要重新赋值,否则优先用const(减少意外修改)

    1
    2
    const API_URL = "https://api.example.com";
    const config = { timeout: 5000 };
  2. **需要重新赋值时用 let**
    替代var的所有场景

    1
    2
    let count = 0;
    count = processItems(items);
  3. **避免使用 var**
    除特殊兼容场景外不应使用

  4. 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
// 误区1:const不能修改对象
const user = { name: "Alice" };
user.name = "Bob"; // ✅ 允许

// 误区2:循环中的const
for (const i = 0; i < 3; i++) { // ❌ i++导致重新赋值报错
console.log(i);
}

// 正确用法
for (const item of [1,2,3]) { // ✅ 每次迭代创建新绑定
console.log(item);
}

浏览器兼容性

  • let/const:ES6+(现代浏览器全支持,IE11部分支持)
  • 旧环境需通过Babel转译为ES5
1