var与let的共同点
都是声明一个变量,都可以先声明后赋值,都可以连续声明多个变量以逗号隔开
var与let的不同点
1、let 声明的范围是块作用域,而 var 声明的范围是函数作用域。
let 声明的age 变量之所以不能在 if 块外部被引用,是因为它的作用域仅限于该块内部
function fun() {
if (true) {
var name = 'Matt';
console.log(name); // Matt
}
console.log(name); // Matt
}
fun();
function fun2() {
if (true) {
let age = 26;
console.log(age); // 26
}
console.log(age); // 报错
}
fun2();
快作用域中var可以多次声明一个变量,而let出现冗余变量则会报错。
var name;
var name;
let age
let age; // 报错
对声明冗余报错不会因混用 let 和 var 而受影响。这两个关键字声明的并不是不同类型的变量, 它们只是指出变量在相关作用域如何存在。
var name;
let name; // SyntaxError
let age;
var age; // SyntaxError
2. 暂时性死区
let 声明的变量不会在作用域中被提升 var关键字声明的变量会自动提升到函数作用域顶部
// var在声明之前使用不会报错
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined
// age 不会被提升会报错
function fun() {
console.log(age); // ReferenceError:age 没有定义
let age = 26;
}
3、全局声明
var声明的变量会是window的属性,使用 let 在全局作用域中声明的变量不会成为 window 对象的属。
var name = 'Matt';
console.log(window.name); // 'Matt'
let age = 26;
console.log(window.age); // undefined
4、var声明的变量可以省略var,如果省略则是全局变量,let声明的变量不可省略let;
5、for 循环中的var let 声明
var定义的 for 循环定义的迭代变量会渗透到循环体外部: 改成使用 let 之后,这个问题就消失了,因为迭代变量的作用域仅限于 for 循环块内部:
for (var i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // 5
for (let i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // ReferenceError: i 没有定义
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 实际上会输出 5、5、5、5、5
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 会输出 0、1、2、3、4
之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。 而在使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。 每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循 环执行过程中每个迭代变量的值。
6、const 声明
const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误。 const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制。