JavaScript中var、let、const的区别简要介绍
1.var声明的是函数级作用域,let和const声明的是块级作用域
function myFunc() {
var a = 1
}
console.log(a) // caught ReferenceError: a is not defined
变量a定义在了函数myFunc里面,当我们企图在函数外面打印变量a时会抛出ReferenceError——引用不存在的变量。
function myFunc() {
let a = 1
const a1 = 1
}
console.log(a) // caught ReferenceError: a is not defined
console.log(a1) // caught ReferenceError: a1 is not defined
if(true) {
let b = 1
const b1 = 1
}
console.log(b) // caught ReferenceError: b is not defined
console.log(b1) // caught ReferenceError: b1 is not defined
while(true) {
let c = 1
const c2 = 1
break
}
console.log(c) // caught ReferenceError: c is not defined
console.log(c1) // caught ReferenceError: c1 is not defined
{
let d = 1
const d2 = 1
}
console.log(d) // caught ReferenceError: d is not defined
console.log(d2)// caught ReferenceError: d1 is not defined
上面的代码除了myFunc之外,在if、while、{},中使用let和cosnt定义的变量,在外部打印时都会抛出ReferenceError。所以什么是块级作用域?其实块级作用域就是用花括号{}界定的,包括function块、if块、while块,甚至就单独的花括号{}也是。
2.var声明的变量存在变量提升, let和const声明严格意义上也存在变量提升,但因为暂时性死区的原因,虽然提升了但是在执行到声明语句之前是不可用的。
console.log(a)
var a = 1 // undefined
在声明a变量之前打印a变量是undefined——已经声明但是没有赋值,而不是预想ReferenceError,说明var声明存在着变量提升现象。什么是变量提升?其实var声明会被拿到函数或全局作用域的顶部,位于作用域所有代码之前。这个现象叫做“提升”。提升让同一作用域中的代码不必考虑变量是否已经声明就可以直接使用。上述代码就是在声明a变量之前直接使用了a变量。
console.log(a)
let a = 1 // Cannot access 'a' before initialization
console.log(b)
const b = 1 // Cannot access 'b' before initialization
在声明a、b变量之前打印a、b变量是Cannot access ‘xx’ before initialization——在初始化之前不能访问“xx”,说明let和const声明在严格意思上也是存在变量提升的。虽然已经声明变量,但是实际上不能再声明之前使用let和const变量。这个现象叫做“暂时性死区”。
3.var声明的变量可以重复声明,在同一块作用域内let和const变量不能重新声明
var a = 1
var a = 2
console.log(a) // 2
let a = 1
let a = 2 // caught SyntaxError: Identifier 'a' has already been declared
const b = 1
const b = 2 // caught SyntaxError: Identifier 'b' has already been declared
var声明变量a为1,再次声明a为2,通过打印可以看到操作成功。但是通过let和const声明的变量会抛出SyntaxError——语法错误,变量已经定义过了不能重复定义。
4.const对比var和let也有自己独特的点:声明的变量必须同时初始化为某个值;一经过声明,在其声明周期的任务时候都不能重新赋值,但是只应用到顶级原语或者对象,即赋值为对象的const变量不能再被重新赋值为其他引用值,但是对象的键则不受限制
var a
console.log(a) // undefiend
let a
console.log(a) // undefiend
const a // caught SyntaxError: Missing initializer in const declaration
上面代码分别使用var、let、const声明变量a,但是都没有初始化。var和let默认赋值了undefined,const声明则抛出SyntaxError,声明中缺少初始化。
var a = 1
a = 2
console.log(a) // 2
let a = 1
a = 2
console.log(a) // 2
const a = 1
a = 2 // caught TypeError: Assignment to constant variable.
const a = {
a:1
b:2
}
a = {
a:1
c:2
} // caught TypeError: Assignment to constant variable.
const a = {
a:1,
b:2
}
a.a = 2
console.log(a) // {a: 2, b: 2}
上面代码分别使用var、let、const声明变量a,并进行了重新赋值。var和let都重新赋值成功,const声明则抛出TypeError——类型错误,对常量进行了赋值。const声明变量a,并赋值为一个对象。重新赋值为一个新对象,任然适用TypeError,但改变对象里面的键值则是不受影响的。