作為一個(gè)JS初學(xué)者,我一直是對(duì)ES6各種奇妙的語(yǔ)法帶有一絲敬畏的.從var-let,promise,解構(gòu),到各種神奇的const騷操作,一直讓我感覺(jué)ES6用的好的人似乎代碼中包含著魔力.
今天在看知乎的時(shí)候,我發(fā)現(xiàn)了方方提的這樣一個(gè)問(wèn)題.
https://www.zhihu.com/question/62966713

x
lex x=x
x
let x
第一個(gè)第二個(gè)的報(bào)錯(cuò)自然好理解,不用多廢話.但是第三個(gè)和第四個(gè)就比較詭異了:如果我調(diào)用x,那么會(huì)提示x未被定義.但是當(dāng)我想定義x的時(shí)候,x又是已經(jīng)被聲明的?
我發(fā)現(xiàn)以我的知識(shí)無(wú)法理解這個(gè)問(wèn)題.
于是看了一下底下的回答:

賀老的回答已經(jīng)指出了問(wèn)題的關(guān)鍵,但是對(duì)于我來(lái)說(shuō),還是理解的比較困難.
然后看了孫北吉 的回答,感覺(jué)自己又懂了一些.最后看了方方的博客,感覺(jué)自己似乎還是不太懂.于是嘗試自己解釋并總結(jié)一下.
問(wèn)題的本質(zhì)就是JS 變量的「創(chuàng)建create、初始化initialize 和賦值assign」.
在第一個(gè)報(bào)錯(cuò)直接輸入x中,JS做了這樣的操作:
在當(dāng)前環(huán)境中進(jìn)行查找x.
因?yàn)槭侨汁h(huán)境 ,直接拋出一個(gè) ReferenceError,提示x不存在.
在第二個(gè)報(bào)錯(cuò)lex x=x中:
lex x=x是一個(gè)RHS查詢,它會(huì)直接進(jìn)行值的查找并通知引擎做這些事:
1. 創(chuàng)建變量.
2. 開(kāi)始執(zhí)行代碼(到現(xiàn)在為止,還未初始化)
3. 將x進(jìn)行初始化為undefined.(這個(gè)操作并不是賦值,僅僅是初始化)
4. 執(zhí)行RHS操作將x賦值給x.(這才是賦值操作)
因?yàn)槲覀兊某跏蓟Z(yǔ)句與賦值語(yǔ)句是同一句,所以我們的let x=x同時(shí)執(zhí)行了3\4步的操作.但是這里就出現(xiàn)了一個(gè)問(wèn)題,這一句話是錯(cuò)的.在報(bào)錯(cuò)的同時(shí),第三步已經(jīng)執(zhí)行完成了,而第四步就沒(méi)有辦法進(jìn)行,在報(bào)錯(cuò)的同時(shí)也取消掉了第三步進(jìn)行的對(duì)x的初始化.也就是說(shuō)這個(gè)值已經(jīng)進(jìn)行了變量創(chuàng)建,但是并未初始化.所以:
在第三個(gè)報(bào)錯(cuò)x中:
這個(gè)變量x在當(dāng)前的環(huán)境中已經(jīng)存在(已經(jīng)被創(chuàng)建過(guò)),但是事實(shí)上這個(gè)變量并未進(jìn)行初始化,也就無(wú)法進(jìn)行各種操作以及訪問(wèn)了.此時(shí)就會(huì)拋出一個(gè)Reference Error.
在第四個(gè)報(bào)錯(cuò)let x中:
在此處我們嘗試著進(jìn)行了let x,實(shí)際上執(zhí)行的就是第二個(gè)報(bào)錯(cuò)的第一步-創(chuàng)建變量.但是變量已經(jīng)被創(chuàng)建,所以會(huì)提示變量已存在.就這樣,我們得到了一個(gè)已經(jīng)被創(chuàng)建但是并未被聲明且無(wú)法被訪問(wèn)的變量.
這就是我的理解,如果有錯(cuò)誤,還請(qǐng)看到這里的你指正.謝謝.
So.Because JavaScript.