let 聲明會提升嗎?
昨天我上課的時候跟飢人谷的學生講了《let 聲明的五個特點》,其中一個就是「let 聲明會提升到所在塊的頂部」,然而今天早上有個學生就問我了:
MDN 上說 let 不會提升,為什麼你說 let 會提升呢?
當時我心裡一方:難道我講錯了?
於是我看了 MDN 英文版的原文,發現寫的也是:
In ECMAScript 2015, let do not support Variable Hoisting, which means the declarations made using "let", do not move to the top of the execution block.
看來我真的錯了?於是我繼續翻看 ECMA-262.pdf,發現了兩處地方支持我的論點。
首先是 13.3.1 Let and Const Declarations
let and const declarations define variables that are scoped to the running execution context s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable s LexicalBinding is evaluated.
這說明即使是 block 最後一行的 let 聲明,也會影響 block 的第一行。這就是提升(hoisting)。
以及 18.2.1.2 Runtime Semantics: EvalDeclarationInstantiation( body, varEnv, lexEnv, strict)
The environment of with statements cannot contain any lexical declaration so it doesn t need to be checked for var/let hoisting conflicts.
這句話從側面證明了 let hoisting 的存在。
所以,我就把 MDN 的英文版和中文版給糾正過來了:
在 ECMAScript 2015中, let 也會提升到語句塊的頂部。但是,在這個語句塊中,在變數聲明之前引用這個變數會導致一個 ReferenceError的結果
希望被之前 MDN 某個版本誤導的同學周知。
總結一下:
let 聲明會提升到塊頂部
從塊頂部到該變數的初始化語句,這塊區域叫做 TDZ(臨時死區)
如果你在 TDZ 內使用該變數,JS 就會報錯
我可沒說 TDZ 跟 hoisting 等價!
更新:
有些同學還是認為 let 不會提升,試試理解下面的代碼:
let a = 1 { a = 2 let a }
如果 let 不會提升,那麼 a = 2 就會將外面的 a 由 1 變成 2 啊。
運行發現 a = 2 報錯:Uncaught ReferenceError: a is not defined
這說明上面的代碼近似近似近似近似近似近似地可以理解為:(注意看注釋中的 TDZ,早知道我就不寫代碼了,有些人看代碼不看注釋)
let a = 1 { let a // TDZ 開始的地方就是這裡 start a TDZ a = 2 // 由於 a = 2 在 TDZ 中,所以報錯 a // TDZ 結束的地方就是這裡 end a TDZ }
所以,let 提升了。
完。
※用代碼寫靜態表格
※如何設計合理友好的錯誤提示?
※Spring boot學習
※perseus:基於 Mybatis+Spring 的讀寫分離方案
※深度學習思考
TAG:推酷 |
※她離開了所屬社,但是同時聲明會保持女團的活動!
※范冰冰任由謠言滋生無所作為?知情人:發聲明會被落井下石,一直默默調查取證