前言
ES6之前我们声明变量通常都是使用var,但是使用var声明的变量可以重复声明、会提升到顶层、污染全局变量等。ES6之后新增了let和const可以很好的避免了这些。
相同点
let和const有以下几个相同点
块级作用域
如果是在if语句或者for循环里使用var声明变量,那么在外面是可以访问到的。
if (true) {
var uname = "haha";
}
console.log(uname); // haha
for (var i = 0; i < 3; i++) {
}
console.log(i); // 3
使用let和const声明的变量则不会有出现这种情况
if (true) {
let uname = "hehe";
}
console.log(uname); // 报错 uname is not defined
不能重复声明
使用var声明的变量可以重复声明
var uname = "haha";
var uname = "hehe";
console.log(uname); // hehe
使用let和const不可以重复声明
let uname = "haha";
let uname = "hehe"; //报错:Identifier 'uname' has already been declared
没有变量提升
使用var声明的变量可以提升,即先使用再声明
console.log(uname); // undefined
var uname = "haha";
使用let和const没有变量提升
console.log(uname); // 报错 ReferenceError: Cannot access 'uname' before initialization
let uname = "haha";
不与顶层对象挂钩
在浏览器里顶层对象就是window,使用var声明的变量可以直接使用window访问
var uname = "haha";
console.log(window.uname); // haha
使用let和const声明的访问会返回undefined
let uname = "haha";
console.log(window.uname); // undefined
暂时性死区
从一个代码块的开始直到代码执行到声明变量的行之前,let和const声明的变量都处于暂时性死区中。当变量处于暂时性死区之中时,其尚未被初始化,尝试访问变量将抛出错误(ReferenceError)。当代码执行到声明变量所在行时,变量被初始化一个值。如果声明中未指定初始值,则变量会被初始化为undefined。
let uname = "haha";
if (true) {
console.log(uname); // 报错 ReferenceError: Cannot access 'uname' before initialization
let uname = "hehe";
}
不同点
let可以改变,const不可以改变
使用let声明的可以改变,使用const声明的不可以改变(const声明的叫常量)
let uname = "haha";
uname = "hehe"
console.log(uname); // hehe
const uname = "haha";
uname = "hehe"; // 报错 TypeError: Assignment to constant variable.
但是如果使用const 声明的是对象,则可以改变对象里的属性
const user = {
name: "haha"
};
user.name = "hehe";
console.log(user); // {name: 'hehe'}
使用Object.freeze方法可以冻结const声明的对象不被改变,但是也只能冻结最外层的属性不被改变,如果最外层属性的属性值时对象也是可以改变的。
const user = Object.freeze({
name: "haha",
address: {
city: "aaa"
}
});
user.name = "hehe"; // TypeError: Cannot assign to read only property 'name' of object
user.address.city = "bbb";
console.log(user.address); // {city: "bbb"}
let可以没有初始值,const必须要有初始值
let uname;
console.log(uname); // undefined
const uname; // Module parse failed: Unexpected token