var
、 let
和 const
的差异主要体现在作用域、变量提升、重复声明、重新赋值以及在循环中的行为等。
1. var
- 作用域:
var
声明的变量具有函数作用域或全局作用域。在函数内部声明的变量只在函数内部有效,而在函数外部声明的变量在整个函数外部都有效。 - 变量提升:在变量声明之前就可以使用,但值为
undefined
。这是因为变量声明会被提升到函数或全局作用域的顶部。 - 重复声明:允许多次声明同一个变量,后续声明会覆盖前面的声明。
- 重新赋值:可以重新赋值。
function example() {
console.log(x); // 输出 undefined
var x = 10;
console.log(x); // 输出 10
}
example();
console.log(x); // 报错,因为 x 只在 example 函数内部有效
2. let
- 作用域:
let
声明的变量具有块级作用域。在{}
内部声明的变量只在该块内部有效。 - 变量提升:不会发生变量提升,如果在声明之前访问变量会报错。
- 重复声明:不允许在同一作用域内重复声明同一个变量,会报错。
- 重新赋值:可以重新赋值,但不能重新声明。
function example() {
console.log(x); // 报错,因为 x 还未声明
let x = 10;
console.log(x); // 输出 10
}
example();
console.log(x); // 报错,因为 x 只在 example 函数内部有效
3. const
- 作用域:
const
声明的变量具有块级作用域,和let
类似。 - 变量提升:不会发生变量提升,如果在声明之前访问变量会报错。
- 重复声明:不允许在同一作用域内重复声明同一个变量,会报错。
- 重新赋值:不可重新赋值,但对于复杂类型的数据(如数组或对象),虽然不能重新赋值,但可以修改其内部的属性或元素。
const PI = 3.14;
// PI = 3.14159; // 报错,因为 const 声明的变量是常量,不可重新赋值
const arr = [1, 2, 3];
arr.push(4);
console.log(arr); // 输出 [1, 2, 3, 4]
4. 在循环中的行为
在循环中使用 var
会导致变量的共享问题,而使用 let
或 const
可以避免这个问题。
for (var i = 0; i < 5; i ) {
setTimeout(function() {
console.log(i); // 输出 5, 5, 5, 5, 5
}, 100);
}
for (let j = 0; j < 5; j ) {
setTimeout(function() {
console.log(j); // 输出 0, 1, 2, 3, 4
}, 100);
}
由于 var
声明的变量具有函数作用域,循环结束后 i
的值为 5 ,而在第一个循环中, setTimeout
回调函数是在循环结束后才执行的,因此输出的都是 5 。而在第二个循环中, let
声明的变量具有块级作用域,每次循环都会创建一个新的作用域,因此 setTimeout
回调函数中可以访问到当前循环的 j
的值。
在实际开发中,推荐优先使用 let
和 const
来声明变量,以避免潜在的问题。