var
、 let
和 const
的差异主要体现在作用域、变量提升、重复声明、重新赋值以及在循环中的行为等。
var
声明的变量具有函数作用域或全局作用域。在函数内部声明的变量只在函数内部有效,而在函数外部声明的变量在整个函数外部都有效。undefined
。这是因为变量声明会被提升到函数或全局作用域的顶部。function example() {
console.log(x); // 输出 undefined
var x = 10;
console.log(x); // 输出 10
}
example();
console.log(x); // 报错,因为 x 只在 example 函数内部有效
let
声明的变量具有块级作用域。在 {}
内部声明的变量只在该块内部有效。function example() {
console.log(x); // 报错,因为 x 还未声明
let x = 10;
console.log(x); // 输出 10
}
example();
console.log(x); // 报错,因为 x 只在 example 函数内部有效
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]
在循环中使用 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
来声明变量,以避免潜在的问题。