JavaScript碎碎冰:let和var的区别
学的时候看到有时候申明变量关键字用let有时候用var,不知道两个区别是什么所以去查了一下,不想看的省流版:var作用在整个函数里,let作用在当前{}内。
本篇目录
- 作用域
- 变量提升
- 重复声明
- 全局对象属性
- 循环中的表现差异
1. 作用域(Scope)
// var:函数作用域
function testVar() {
if (true) {
var x = 10; // 函数作用域
}
console.log(x); // 10 - 在if块外部仍然可访问
}
//顺便,var还可以这样一次性定义好多个
function foo() {
var
x = 1, // x初始化为1
y = x + 1, // y初始化为2
z, i; // z和i为undefined
// 其他语句...
}
}
// let:块级作用域
function testLet() {
if (true) {
let y = 20; // 块级作用域
}
console.log(y); // ReferenceError: y is not defined
}
特殊情况:函数嵌套
JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行
function foo() {
var x = 1;
function bar() {
var y = x + 1; // bar可以访问foo的变量x!
}
var z = y + 1; // ReferenceError! foo不可以访问bar的变量y!
}
function foo() {
let x = 1; // 使用let声明
function bar() {
let y = x + 1; // bar仍然可以访问foo的变量x!
console.log(y); // 输出2
}
bar();
let z = y + 1; // ReferenceError! foo仍然不能访问bar的变量y!
}
2. 变量提升(Hoisting)
var - 提升并赋值为undefined
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有用var申明的变量“提升”到函数顶部:
console.log(a); // undefined
var a = 5;
console.log(a); // 5
// 相当于:
var a;
console.log(a); // undefined
a = 5;
console.log(a); // 5
let - 提升但不初始化(暂时性死区)
console.log(b);
// ReferenceError: Cannot access 'b' before initialization
let b = 10;
3. 重复声明
//var:允许重复声明
var x = 1;
var x = 2; // 不会报错
console.log(x); // 2
// let:不允许
let y = 1;
let y = 2; // SyntaxError: Identifier 'y' has already been declared
4. 全局对象属性
//var:会成为全局对象的属性
var globalVar = "hello";
console.log(window.globalVar); // "hello" (在浏览器环境中)
//let:不会
let globalLet = "world";
console.log(window.globalLet); // undefined (在浏览器环境中)
5. 循环中的表现差异
//var
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出3次3
}
// let
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出0, 1, 2
}
总结
| 特性 | var | let |
|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 |
| 变量提升 | 提升并初始化为undefined | 提升但不初始化(暂时性死区) |
| 重复声明 | 允许 | 不允许 |
| 全局属性 | 会成为window的属性 | 不会成为window的属性 |
浙公网安备 33010602011771号