指「變數宣告」或是「函式宣告」會被提升到該作用域的頂端,但賦值不會被提升。
也就是只有宣告會被提升,賦值不會。
範例:
console.log(a); // undefined
var a = 5;
console.log(a); // 5
var a
會先被提升到作用域的頂端,可以看成以下:var a;
console.log(a); // undefined
a = 5;
console.log(a); // 5
console.log(a)
不會報錯,是因為在這階段會為變數保留記憶體空間,初始值為undefined
。a = 5
,因為5賦值給變數a了,所以第四行console.log(a)
才能印出5
。後來有ES6的let
、const
,兩者變數宣告一樣會提升,但JavaScript確保變數在賦值之前不會被使用。
因此變數在賦值之前會進入暫時性死區(TDZ,Temporal Dead Zone)。在TDZ時,變數是不可用的。
MDN關於TDZ暫時性死區的說明:
A variable declared with let, const, or class is said to be in a "temporal dead zone" (TDZ) from the start of the block until code execution reaches the place where the variable is declared and initialized.
把剛剛範例改成let宣告看看:
console.log(a); // ReferenceError: a is not defined
let a = 5;
console.log(a); // 5
let a = 5
之前,變數a
進入了TDZ,因此在第一行console.log(a)
會報錯。a
被賦值let a = 5
,就能順利印出值了。函式宣告也會被提升,跟變數不一樣的是,函式在提升時,是保留函式整個內容。
原先撰寫函式宣告完再執行函式呼叫,在這裡把函式呼叫sayHello()
放到程式碼最上方,觀察看看:
sayHello(); // "Hello!"
function sayHello() {
console.log("Hello!");
}
Hello!
function sayHello() {
console.log("Hello!");
}
sayHello(); // "Hello!"
所以函式sayHello順利印出"Hello!"
。
以上分享~謝謝!
MDN - Hoisting
MDN - let&TDZ
JS 原力覺醒 Day06 - 提升 Hoisting