作用域:
let具有块级作用域,只在声明的块或语句内部可见。var具有函数级作用域,可在整个函数内部访问。
以下是一个示例,展示了 let 和 var 的作用域区别:
function example() {
if (true) {
let x = 10; // 块级作用域内的变量
var y = 20; // 函数级作用域内的变量
console.log(x); // 输出 10
console.log(y); // 输出 20
}
console.log(x); // 错误:x 未定义
console.log(y); // 输出 20
}
example();
在上面的示例中,x 是使用 let 声明的变量,它只在 if 语句块内部可见。而 y 是使用 var 声明的变量,它在整个函数内部都可见。
变量提升:
- 使用
let声明的变量不存在变量提升,必须在声明之后才能访问。 - 使用
var声明的变量会被提升到其作用域的顶部,可以在声明之前访问。
以下是一个示例,展示了 let 和 var 的变量提升区别:
function example() {
console.log(x); // 输出 undefined
var x = 10;
console.log(y); // 错误:y 未定义
let y = 20;
}
example();
在上面的示例中,使用 var 声明的变量 x 在声明之前可以访问,但它的值为 undefined。而使用 let 声明的变量 y 在声明之前是不可访问的。
重复声明:
- 使用
let声明的变量不允许在同一作用域内重复声明。 - 使用
var声明的变量允许在同一作用域内重复声明,并且后面的声明会覆盖前面的声明。
以下是一个示例,展示了 let 和 var 的重复声明区别:
function example() {
let x = 10;
let x = 20; // 错误:无法重新声明块级作用域的
var x = 10;
var x = 20; // 重复声明,覆盖前面的声明
}
example();
闭包
闭包与 var:
使用 var 声明的变量在闭包中具有共享的作用域。这意味着闭包内部的函数可以访问和修改外部函数中声明的变量。
function example() {
var x = 10;
function inner() {
console.log(x); // 10
}
inner();
}
example();
在上面的示例中,inner 函数可以访问外部函数 example 中声明的变量 x。
闭包与 let:
使用 let 声明的变量在闭包中具有独立的作用域。每次迭代或调用闭包时,都会创建一个新的变量实例。
function example() {
for (let i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i); // 0, 1, 2, 3, 4
}, 1000);
}
}
example();
在上面的示例中,setTimeout 函数中的回调函数形成了闭包。使用 let 声明的变量 i 在每次迭代时都会创建一个新的实例,因此每个闭包都能够访问到正确的值。
相比之下,如果我们使用 var 声明变量 i,则所有的闭包都会共享同一个 i,导致输出结果为 5。
function example() {
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i); // 5, 5, 5, 5, 5
}, 1000);
}
}
example();
在这个示例中,由于 var 声明的 i 在全局作用域中共享,所有的闭包都使用了相同的 i 值。
通过使用 let 声明变量,我们确保了每个闭包都可以访问到正确的值,而不会受到循环的影响。