三者之间的区别

1.声明后的可变性

①**var**:变量可以随时重新赋值,也可以重复声明。

1
2
3
var a = 10;
var a = 20; // 允许重复声明
a = 30; // 可以重新赋值

②**let**:变量可以重新赋值,但不能重复声明。

1
2
3
4
let b = 10;
// let b = 20; // 报错:不能重复声明
b = 30; // 可以重新赋值

③**const**:变量声明后不能重新赋值,也不能重复声明。

1
2
3
4
const c = 10;
// c = 20; // 报错:不能重新赋值
// const c = 30; // 报错:不能重复声明

2.作用域

①**var**:受函数作用域限制,声明的变量在整个函数内部都可访问,不受块级作用域的限制。

1
2
3
4
5
if (true) {
var x = 10; // 函数作用域
}
console.log(x); // 10:块外仍然能访问

②**let** 和 **const**:采用块级作用域,变量只能在声明的块内使用,块外无法访问。

1
2
3
4
5
6
7
if (true) {
let y = 20;
const z = 30;
}
// console.log(y); // 报错:块外不能访问
// console.log(z); // 报错:块外不能访问

3.变量提升

①**var**:变量会提升到作用域顶部,并初始化为 undefined,可以在声明之前访问.

1
2
3
console.log(a); // undefined:变量已提升
var a = 10;

②**let** 和 **const**:同样会提升到作用域顶部,但不会初始化,在声明之前访问会报错(称为“暂时性死区”)。

1
2
3
4
5
6
// console.log(b); // 报错:在声明前不能访问
let b = 20;

// console.log(c); // 报错:在声明前不能访问
const c = 30;

4.是否必须初始化

①**varlet**:可以声明而不赋值,默认值为 undefined

1
2
3
4
5
var g;
let h;
console.log(g); // undefined
console.log(h); // undefined

②const:声明时必须同时赋值,否则报错.

1
2
3
// const i; // 报错:必须初始化
const j = 10; // 正确

5.是否绑定到全局对象

①**var**:在全局作用域中声明的变量会绑定到 window 对象(浏览器环境)。

1
2
3
var d = 10;
console.log(window.d); // 10

②**let** 和 **const**:不会绑定到 window 对象。

1
2
3
4
5
let e = 20;
const f = 30;
console.log(window.e); // undefined
console.log(window.f); // undefined

PS:

变量提升

定义

是 JavaScript 的一种机制,指在代码执行阶段,变量声明和函数声明会被提升到其所在作用域的顶部进行处理。换句话说,尽管声明出现在代码的后面,JavaScript 引擎会在执行代码之前,将这些声明在内存中提升到作用域的顶部,但不会提升赋值操作。

核心点

1.声明提升:

变量和函数的声明会被移动到作用域顶部。

2.赋值不提升:

只有声明被提升,赋值仍然停留在原来的位置。

3.影响作用域:

变量提升遵循作用域规则,声明在全局作用域或函数作用域的顶部进行提升。

示例

1.变量声明提升
1
2
3
4
5
6
console.log(a); // 输出:undefined
var a = 10;




等价于:

1
2
3
4
var a; // 声明被提升
console.log(a); // undefined
a = 10; // 赋值在原位置

2.函数声明提升
1
2
3
4
5
sayHello(); // 输出:"Hello"
function sayHello() {
console.log("Hello");
}

等价于:

1
2
3
4
5
function sayHello() {
console.log("Hello");
}
sayHello(); // "Hello"

3.letconst 的“暂时性死区”
1
2
3
console.log(b); // 抛出错误:Cannot access 'b' before initialization
let b = 20;

尽管 b 的声明被提升,但它在初始化前不可访问,形成“暂时性死区”。