一、前言
這兩天在學(xué)react-native暫時(shí)感覺沒什么好寫的,正好公司新來的前端妹紙對于ES6不太了解,準(zhǔn)備給她講講
ES6狹義的理解就是ES2015,實(shí)際上是指新一代ES規(guī)范,網(wǎng)上的教程鋪天蓋地,畢竟都快2020了
像vue、react、node等等,開發(fā)都會用到ES6的知識,它能夠大幅度提高我們的Coding效率
我對它的理解肯定不如各位大佬,所以這里貼出我的《深入理解ES6》的學(xué)習(xí)筆記工同學(xué)們參考
同時(shí)推薦以下的學(xué)習(xí)資料供同學(xué)們系統(tǒng)的學(xué)習(xí):
1、阮一峰老師的《ES6標(biāo)準(zhǔn)入門》

2、《深入理解ES6》

二、var聲明及變量提升(Hoisting)機(jī)制
ES5的var關(guān)鍵字我想任何一個(gè)前端開發(fā)者都不陌生,它被用來聲明一個(gè)變量。
看以下的例子:

如果對Hoisting機(jī)制不了解的同學(xué)可能會認(rèn)為:
上面的代碼在參數(shù)condition為true的時(shí)候才會定義變量value,但是在else里我們打印value居然是undefined而不是拋出一個(gè)ReferenceError
其實(shí)并不是這樣的
無論var在代碼的任何地方聲明變量,事實(shí)上,在js預(yù)編譯的時(shí)候,js引擎會把上面的代碼解析成:

這樣寫相信同學(xué)們都能理解了,變量value的聲明其實(shí)被提到了函數(shù)的頂部,而初始化的操作被留在了原來的位置
那么我們看 變量提升 的定義:
JavaScript 中,函數(shù)及變量的聲明都將被提升到函數(shù)的最頂部。 // 菜鳥教程
這樣的形式好像并不符合我們的預(yù)期,有時(shí)候甚至?xí)斐梢恍゜ug
三、塊級作用域和塊級聲明
為了解決上面的問題,ES6新增了?塊級作用域(詞法作用域)?的概念:
塊級作用域存在于?函數(shù)內(nèi)部?的?塊(兩個(gè)花括號之間的區(qū)域)中。
而塊級聲明聲明的變量在聲明的塊之外無法被訪問。
let聲明
它的用法類似于var,用來聲明一個(gè)變量。它有以下特點(diǎn):
1、不會變量提升
因此用let代替var聲明變量就可以把變量的作用域限制在當(dāng)前的代碼塊中

除了在value定義的代碼塊,也就是condition為true的情況下,value是有值的
執(zhí)行流離開if塊,value立即被銷毀,使用value值都會拋出一個(gè)引用錯(cuò)誤
2、禁止重聲明

無論另一個(gè)變量是用var還是let聲明的
同一作用域中不能用let重復(fù)聲明已經(jīng)存在的標(biāo)識符,否則會拋出一個(gè)語法錯(cuò)誤
const聲明
用來聲明一個(gè)常量。它有以下特點(diǎn):
1、不會變量提升
2、禁止重聲明
3、值一旦被設(shè)定后不可更改
否則拋出語法錯(cuò)誤
tips:常量如果是對象,那么對象中的值可以修改

原因:const聲明不允許修改綁定,但允許修改值
4、必須初始化
否則拋出語法錯(cuò)誤,這是由特點(diǎn)3決定的

四、暫時(shí)性死區(qū)(Temporal Dead Zone,TDZ)
在let或const聲明之前訪問這些變量,會拋出引用錯(cuò)誤
原理:
JS引擎在掃描代碼發(fā)現(xiàn)變量聲明時(shí),要么將他們提升至作用域頂部(遇到var聲明),要么將聲明放到TDZ中(遇到let和const聲明)。訪問TDZ中的變量會觸發(fā)運(yùn)行時(shí)錯(cuò)誤。只有執(zhí)行過變量聲明語句后,變量才會從TDZ中移出,然后才可正常訪問。

五、循環(huán)中的let聲明
同學(xué)們應(yīng)該常常這樣寫for循環(huán):

由于Hoisting,i的聲明提升到函數(shù)頂部,導(dǎo)致在循壞外部依舊可以訪問到i,輸出是10
在沒有ES6之前,由于這個(gè)特性,我們很難在循環(huán)中創(chuàng)建函數(shù),看以下例子:

函數(shù)租后會輸出10次10,因?yàn)?,i由于之前for循環(huán)里的自增,已經(jīng)變成了10。在forEach循環(huán)的時(shí)候,每次迭代都同時(shí)共享變量i。
這明顯與函數(shù)的本意不符!
為了解決這個(gè)問題,開發(fā)者們使用了 立即執(zhí)行函數(shù)(IIFE):

立即執(zhí)行函數(shù),顧名思義就是在函數(shù)定義的時(shí)候立即執(zhí)行一次
格式是這樣的:
(function 函數(shù)名 (形參)? {?
????// 函數(shù)體?
})(實(shí)參)
通過這種方式的確是實(shí)現(xiàn)了我們的功能,但是無疑非常復(fù)雜!
直到ES6為我們提供了let這樣的塊級聲明:

這樣做一樣可以達(dá)到預(yù)期的效果
原理是:let聲明每次迭代都會創(chuàng)建一個(gè)新變量,并以之前迭代中的同名變量的值將其初始化
這個(gè)特性對于for-of循環(huán)和for-in循環(huán)來說也是一樣的
六、循環(huán)中的const聲明
for循環(huán)
例如:

在循環(huán)一次后,拋出語法錯(cuò)誤
原因是,在for循環(huán)中i++試圖修改常量的值
for-of循環(huán)、for-in循環(huán)
此時(shí)const的行為與let一致
七、全局作用域綁定
var被用于全局作用域時(shí),會創(chuàng)建一個(gè)新的全局變量作為全局對象(瀏覽器中是window對象,node中是global對象)的屬性
而let和var被用于全局作用域時(shí),會在全局作用域下創(chuàng)建一個(gè)新的綁定,但改綁定不會添加為全局對象的屬性
有點(diǎn)繞口,什么意思?舉例說明:

所以,如果不想為全局對象創(chuàng)建屬性,那么let和const安全的多
八、最佳實(shí)踐
默認(rèn)使用const,只在確實(shí)需要改變變量的值時(shí)使用let。這樣就可以在某種程度上實(shí)現(xiàn)代碼的不可變,從而防止某些錯(cuò)誤的發(fā)生。
九、結(jié)語
感謝尼古拉斯老師,講的很好,通俗易懂,短短的篇幅就講清楚了let、const和var的區(qū)別,以及一些使用經(jīng)驗(yàn)!
es6的內(nèi)容,比較多,接下來一段時(shí)間可能每天的更新都是es6相關(guān),當(dāng)然,有些感覺不是很常用的內(nèi)容可能不會講。。。
希望這篇文章能夠幫助同學(xué)們理解ES6的一些基礎(chǔ)知識,如果對您有所幫助,請關(guān)注、點(diǎn)贊并收藏,有其他問題也可以留言或私信,歡迎討論!