JS中let和var变量区别
概念
- 作用域:
var
是函数作用域,let
是块级作用域。 - 提升:
var
会被提升并初始化为undefined
,let
也会提升,但在声明前访问会导致错误。 - 重声明:
var
允许在同一作用域内重复声明,let
不允许。 - 循环中的行为:在
for
循环中,使用let
会创建一个新的作用域,而var
只会有一个作用域。
因此,通常建议使用 let
来声明变量,以避免由于 var
的作用域和提升行为导致的潜在问题。
1. var
和 let
的作用域
-
var
的作用域是 函数作用域,即它声明的变量只在当前函数内有效。如果在函数外部声明了var
变量,则该变量是全局的。 -
let
的作用域是 块级作用域,即它声明的变量仅在当前代码块(如if
语句、for
循环等)内有效。
例子:
function testVar() {
if (true) {
var x = 10;
}
console.log(x); // 输出 10,x 是函数作用域
}
function testLet() {
if (true) {
let y = 20;
}
console.log(y); // 报错 ReferenceError: y is not defined,y 仅在块级作用域内有效
}
2. var
和 let
的提升(Hoisting)
-
var
声明的变量会被提升到函数或全局作用域的顶部,但它们的值不会提升,初始化的值保持在声明时的位置。 -
let
声明的变量同样会被提升,但它们不会被初始化。在变量声明之前访问它们会导致ReferenceError
,这被称为“暂时性死区”(TDZ,Temporal Dead Zone)。
例子:
function testHoisting() {
console.log(a); // 输出 undefined,变量被提升但没有初始化
var a = 5;
console.log(b); // 报错 ReferenceError: Cannot access 'b' before initialization
let b = 10;
}
testHoisting();
3. var
和 let
的重声明
-
var
允许在同一作用域内重复声明变量。 -
let
不允许在同一作用域内重复声明同一变量,否则会抛出错误。
例子:
var x = 10;
var x = 20; // 不报错,x 会被重新赋值为 20
let y = 30;
let y = 40; // 报错 SyntaxError: Identifier 'y' has already been declared
4. var
和 let
在循环中的表现
在使用 var
和 let
声明循环变量时,它们的作用域也不同。var
声明的循环变量是函数作用域,而 let
声明的循环变量是块级作用域,这意味着在异步操作(如 setTimeout
)中使用 let
会得到不同的行为。
例子:
// 使用 var
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 输出 3 次 3,因为 var 是函数作用域,i 在整个函数内都可见
}, 1000);
}
// 使用 let
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 输出 0, 1, 2,let 是块级作用域,每次迭代都有一个新的 i
}, 1000);
}