浅谈ES的let和const
ES6提供了let和const的新特性,同时也是新的变量声明方式,它能解决以往var变量声明存在的隐性弊端问题。
Let
let的出现,解决了ES中块级作用域的需求。回顾在这之前,Js并没有没什么类似其他编程语言中块级作用域的概念(比如var声明的全局变量属于全局对象的属性,即意味着我们可以通过window.变量名的方式访问到),因此这也导致了很多变量污染的问题,进而导致产生更多奇怪的问题。
块级作用域
for (var i = 0; i < 10; i++) {
console.log(i)
}
console.log(i) // i=10
for (let j = 0; j < 10; j++) {
console.log(j)
}
console.log(j) // ReferenceError: j is not defined
如上所示,如果我们在循环内部使用var
声明一个变量的话,当循环结束后,该变量并没有被回收,仍然能被使用,出现了循环中的乱象。而当我们使用let
的时候,当离开这个块的时候,该变量就会回收,因此继续使用就会报错。
暂时性死区
var i = 5;
(function a() {
console.log(i) // undefined
var i = 10
})()
let j = 55;
(function b() {
console.log(j) // ReferenceError: j is not defined
let j = 77
})()
看以上代码,由于var
它具有变量提升的功能,所以该声明语句会移到最上面执行,也就是等价于以下代码:
var i = 5;
(function a() {
var i
console.log(i) // undefined
i = 10
})()
let j = 5;
(function b() {
console.log(j) // ReferenceError: j is not defined
let j = 10
})()
但是,如果将var
换成let
的话却会报错,也就是说let
并不具备变量提升的特性。
这个特性叫做临时性死区,也可以把它当成变量提升的一种特殊情况。也就是说,当你在一个块里面,利用let
声明一个变量的时候,在块的开始部分到该变量的声明语句之间,我们称之为临时性死区,你不可以在这个区域内使用该变量,直到遇到其let
语句为止。比如:
var i = 5; // j的临时性死区
(function a() {
var i
console.log(i) // undefined
i = 10
})() // j的临时性死区
// j的临时性死区
let j = 5; // 接下来可以使用let了
console.log(j)
console.log(j+10)
(function b() {
console.log(j) // 新的j的临时性死区
let j = 50 //又有一个声明语句,从这个函数的开始部分到这里,都是新的j的临时性死区
})()
之所以说它是变量提升的一种特殊情况,是因为无论你在块的哪一个地方利用let
声明了一个变量,都会产生一个从块的开始部分到该变量声明语句的临时性死区。
对var或者是直接声明全局变量来说,变量都可以未声明或者在声明语句之前就使用,而使用了let之后,该变量必须在其声明语句后,才能使用,否则就会报错。这就在一定程度上避免了变量污染的情况。
const
const,顾名思义,就是声明一个常量。
它有以下特点:
1.必须初始化
2.不可重复声明
3.作用域:块级作用域
4.不存在变量提升现象(与let相同)
const
和let
声明的变量很类似,不同之处在于变量的声明和初始化必须一起进行,且之后值不可随意修改。只声明不赋值也会报错:Uncaught SyntaxError: Missing initializer in const declaration。
对于声明数值的可变性,有以下两种情况:
当变量类型为number,string,boolean,null时,数值是常量,即在初始化之后不允许修改,否则报错 Uncaught TypeError: Assignment to constant variable。
当变量为对象,数组时,其内容可以修改,因为对象,数组等变量存放的是地址,地址不允许修改,但是地址里面存放的内容是可以修改的。