作為一個JS初學(xué)者,我一直是對ES6各種奇妙的語法帶有一絲敬畏的.從var-let,promise,解構(gòu),到各種神奇的const騷操作,一直讓我感覺ES6用的好的人似乎代碼中包含著魔力.
今天在看知乎的時候,我發(fā)現(xiàn)了方方提的這樣一個問題.
https://www.zhihu.com/question/62966713
x
lex x=x
x
let x
第一個第二個的報錯自然好理解,不用多廢話.但是第三個和第四個就比較詭異了:如果我調(diào)用x,那么會提示x未被定義.但是當(dāng)我想定義x的時候,x又是已經(jīng)被聲明的?
我發(fā)現(xiàn)以我的知識無法理解這個問題.
于是看了一下底下的回答:
賀老的回答已經(jīng)指出了問題的關(guān)鍵,但是對于我來說,還是理解的比較困難.
然后看了孫北吉 的回答,感覺自己又懂了一些.最后看了方方的博客,感覺自己似乎還是不太懂.于是嘗試自己解釋并總結(jié)一下.
問題的本質(zhì)就是JS 變量的「創(chuàng)建create穷吮、初始化initialize 和賦值assign」.
在第一個報錯直接輸入x中,JS做了這樣的操作:
在當(dāng)前環(huán)境中進(jìn)行查找x.
因為是全局環(huán)境 ,直接拋出一個 ReferenceError,提示x不存在.
在第二個報錯lex x=x中:
lex x=x是一個RHS查詢,它會直接進(jìn)行值的查找并通知引擎做這些事:
1. 創(chuàng)建變量.
2. 開始執(zhí)行代碼(到現(xiàn)在為止,還未初始化)
3. 將x進(jìn)行初始化為undefined.(這個操作并不是賦值,僅僅是初始化)
4. 執(zhí)行RHS操作將x賦值給x.(這才是賦值操作)
因為我們的初始化語句與賦值語句是同一句,所以我們的let x=x同時執(zhí)行了3\4步的操作.但是這里就出現(xiàn)了一個問題,這一句話是錯的.在報錯的同時,第三步已經(jīng)執(zhí)行完成了,而第四步就沒有辦法進(jìn)行,在報錯的同時也取消掉了第三步進(jìn)行的對x的初始化.也就是說這個值已經(jīng)進(jìn)行了變量創(chuàng)建,但是并未初始化.所以:
在第三個報錯x中:
這個變量x在當(dāng)前的環(huán)境中已經(jīng)存在(已經(jīng)被創(chuàng)建過),但是事實上這個變量并未進(jìn)行初始化,也就無法進(jìn)行各種操作以及訪問了.此時就會拋出一個Reference Error.
在第四個報錯let x中:
在此處我們嘗試著進(jìn)行了let x,實際上執(zhí)行的就是第二個報錯的第一步-創(chuàng)建變量.但是變量已經(jīng)被創(chuàng)建,所以會提示變量已存在.就這樣,我們得到了一個已經(jīng)被創(chuàng)建但是并未被聲明且無法被訪問的變量.
這就是我的理解,如果有錯誤,還請看到這里的你指正.謝謝.
So.Because JavaScript.