能在宣告變數、函式、物件與其他型別前先進行使用,但是初始化並不會被提升。
因為 JavaScript 分成編譯跟執行兩個階段,在編譯階段會把宣告的東西存在記憶體中,而等到執行階段就可以拿出來用了。
EX:
//函式
SayHi("Ivy"); //Hi, Ivy.
function SayHI(name) {
console.log("Hi, " + name + "." );
//變數
console.log(a); //undefined
var a = 1234;
}
剛剛上面的變數a,因為只有宣告會被提升,因此結果出來並不是 ReferenceError: a is not defined
,而賦值的部分沒有,所以才會出現 undefined
,因為所有變數一開始都會被預設為 undefined。
Hoisting 並不是文件規範的詞彙
因為 JavaScript engine 執行時,事實上沒有東西真正被 「Hoist」,所以我們只能說「想像」會比較好理解。
所以剛剛上面的變數a的範例可以想像成:
var a;
console.log(a);
a=1234;
所以會出現undified就不覺得奇怪了。
**小提醒: 如果有變數與函式是同名的宣告,則在優先權上函式的提升會高於變數:
請看下面範例。
EX:
console.log(a); // ƒ a(){return 'Good morning!';}
var a = "Ivy";
function a(){
return 'Good morning!';
}
事實上, let 與 const 是有 hoisting的,但是當你嘗試先宣告再使用時,會出現TDZ error。
他們不會初始化為 undefined,而且在賦值之前試圖取值會發生錯誤(temporal dead zone)。
These variable declarations only become initialized when they are evaluated during runtime. The >time between these variables being declared and being evaluated is referred to as the temporal >dead zone. If you try to access these variables within this dead zone, you will get the >reference error above.
這強迫你不要在宣告前使用他們。
而TDZ error 是為了 const, 因為const 不能被重新賦值(記得所有變數在預設狀態會被設為undifined)
而let是與const一起推出的,let 也是用這樣的模式。
想進一步瞭解可以去看這篇文章,我覺得寫得蠻詳細的
Ashe Li [day21] YDKJS (Scope) : Hoisting ? let 會 Hoist 嗎 ?
參考資料:
How Hoisting Works With ‘let’ and ‘const’ in Javascript
MDN 提升(Hoisting)
Huli 我知道你懂 hoisting,可是你了解到多深?
Shubo 的程式教學筆記