今天學(xué)習(xí)了ES6新增語法中的let與const命令的基本用法和一些特性九妈,這篇博客用以對這兩個(gè)命令的用法的一些總結(jié)反砌。
在寫let與const之前,首先要明白JS中的塊級作用域萌朱。
一宴树、JS中的塊級作用域
- ES6之前JS不支持塊級作用域
在ES6之前,JS是沒有塊級作用域這個(gè)概念的晶疼,只有全局作用域和函數(shù)內(nèi)的局部作用域酒贬,比如在下面的代碼中,for循環(huán)內(nèi)定義的變量 i 實(shí)際上處于全局作用域中翠霍,所以在循環(huán)的外部是可以調(diào)用變量 i 的锭吨,這個(gè) i 就有可能造成變量的污染
for(var i = 0; i < 5; i++){
}
console.log(i) // 5
- 出現(xiàn)
ES6的擴(kuò)展為JS帶來了新的變量聲明方法,其中的let從實(shí)際上為JS新增了塊級作用域的功能寒匙,使用該命令聲明的變量只能在let命令所在的代碼塊中使用零如。
二、let命令
- 與var命令的對比,以及l(fā)et的一些特性
1.let聲明的變量只能在let命令所在代碼區(qū)塊中生效
// var
for(var i = 0; i < 5; i++){
}
console.log(i) // 5
// let
for(let i = 0; i < 5; i++){ // 這個(gè)i只能在這個(gè)for循環(huán)內(nèi)使用
}
console.log(i) // 報(bào)錯(cuò):i is not defined
2.let不存在變量提升
console.log(a) // undefined
console.log(b) // 報(bào)錯(cuò):b未定義
var a = 1
let b = 1
3.因?yàn)閘et不存在變量提升埠况,所以會(huì)有暫時(shí)性死區(qū)
什么是暫時(shí)性死區(qū)?
暫時(shí)性死區(qū)就是在這個(gè)區(qū)塊中的變量未聲明之前棵癣,對該區(qū)塊中的變量的一切調(diào)用都會(huì)報(bào)錯(cuò)
a = 1
let a = 2
// 以上代碼會(huì)報(bào)錯(cuò)
a = 1
{let a = 2}
// 以上代碼不會(huì)報(bào)錯(cuò)辕翰,因?yàn)槁暶髯兞康膮^(qū)塊不一
4.let聲明的變量不能重復(fù)進(jìn)行聲明
let a = 1
var a = 1 // 報(bào)錯(cuò) a已經(jīng)被聲明
const a = 1 // 報(bào)錯(cuò) a已經(jīng)被聲明
- let的使用實(shí)例
因?yàn)閘et命令的出現(xiàn),所以JS有了塊級作用域狈谊,原本因?yàn)樽饔糜騿栴}導(dǎo)致的閉包問題也可以使用let嗎喜命,清零進(jìn)行解決,比如以下經(jīng)典閉包代碼會(huì)一次性輸出5個(gè)5河劝,但需求是輸出01234
for(var i = 0; i < 5; i++){
setTimeout(function(){
console.log(i)
}, 1000)
}
1.ES6之前的解決辦法壁榕,使用一個(gè)變量對 i 的值進(jìn)行暫存
for(var i = 0; i < 5; i++){
(function(e){
setTimeout(function(){
console.log(e)
}, 1000)
})(i)
}
2.出現(xiàn)let后的解決辦法
for(let i = 0; i < 5; i++){
setTimeout(function(){
console.log(i)
}, 1000)
}
- 關(guān)于for循環(huán)作用域的問題
在for循環(huán)中實(shí)際上是有兩個(gè)作用域的,條件設(shè)置的圓括號()內(nèi)是一個(gè)父作用域赎瞎,而代碼塊大括號{}中是一個(gè)子作用域牌里,比如下面代碼可以進(jìn)行區(qū)分
for(let i = 0; i < 5; i++){
let i = 8
console.log(i)
}
// 輸出結(jié)果是5個(gè)8
三、const命令
與let命令的用法類似务甥,const命令也是用來聲明一個(gè)變量牡辽,同時(shí)也只能在聲明的塊級作用域中進(jìn)行使用,但不同的是const聲明變量后敞临,這個(gè)變量就變成了一個(gè)不能進(jìn)行更改的常量态辛。
- const命令的特性
1.聲明的時(shí)候就必須馬上初始化,否則報(bào)錯(cuò)
如下代碼:
const a; // 報(bào)錯(cuò) 未初始化
const a = 1 // 不報(bào)錯(cuò)
2.聲明的值不能改變挺尿,不能重新進(jìn)行賦值
const a = 1
a = 2 // 報(bào)錯(cuò) a已經(jīng)被聲明過
3.與let一樣不存在變量提升
console.log(a) // 報(bào)錯(cuò) a未聲明
const a = 1
4.與let一樣不可重復(fù)進(jìn)行聲明
const a = 1
var a = 1 // 報(bào)錯(cuò) a已經(jīng)被聲明
let a = 1 // 報(bào)錯(cuò) a已經(jīng)被聲明
- 注意點(diǎn)
1.const聲明的變量的值不能改變實(shí)質(zhì)上是變量指向的內(nèi)存地址不能改變奏黑,因此會(huì)有以下兩種情況- 值為簡單類型:
值保存在變量指向的內(nèi)存地址上。 - 值為復(fù)雜類型:
例如對象:值也保存在變量指向的內(nèi)存地址上编矾,但是不同的是熟史,這個(gè)內(nèi)存地址實(shí)際上是一個(gè)指針,指向這個(gè)對象窄俏,那么在實(shí)際上是可以對這個(gè)對象內(nèi)的屬性進(jìn)行賦值的以故,如下代碼:
- 值為簡單類型:
const a = {b:1}
console.log(a.b) // 1
a.b = 2
console.log(a.b) // 2
2.針對上面的問題,如果想讓對象的屬性和值絕對不變裆操,可以使用Object.freeze方法
const a =Object.freeze({b:1})
console.log(a.b) // 1
a.b = 2
console.log(a.b) // 1