什麼是Hoisting,你可能沒注意到的變數、函式宣告規則,了解宣告bug的不同

今天在來了解一個的執行的觀念叫做Hoisting,了解這個觀念可以讓我們更清楚知道整個程式是怎麼在運作的,如果是正常的一列一列規矩的從上而下寫程式,可能不會發現有這個問題

什麼是Hoisting

當我們宣告變數跟函式的時候,就會先幫我們在記憶體建立一個空間,看起來很像是移動到程式的頂端先執行了,但其實他在程式碼中的實際位置沒有變過

整個過程就會像是:JavaScript先過整篇程式 > 找出所有宣告變數跟函式陳述式 > 在記憶體空間幫他們建立好位置 > 開始從頭執行程式碼

先從最簡單的例子開始說明:

宣告一個text1 = 1,那把他顯示出來

var text1 = 1
console.log(text1) // 1

顯示結果沒意外就是1

再來就是常常出現的錯誤:

直接顯示text1,完全沒宣告也沒給值

console.log(text1) //text1 is not defined

顯示結果就是text1 is not defined

因為沒定義所以找不到

接下來我們看個有趣的:

直接顯示text1,但是宣告擺下面,並且給他值

console.log(text1) //undefined
var text1 = 1

顯示結果是undefined

照我們對程式由上而下執行的認知,應該是未定義變數才對,但卻是給予undefined,表示找不到這個text1的值

這就是Hoisting的提升的表現,雖然宣告在下,顯示在上,但在程式開始進行的階段之前,就已經幫你宣告的變數都佔好記憶體的位置

變數相關的Hoisting

變數相關宣告會被提升

text1 = 1
console.log(text1) // 1
var text

變數的值不會提升

var text1
console.log(text1) // undefined
text1 = 1

函式相關的Hoisting

function expression 函式表達式

這種函式宣告方式就是會先將var擺前面來宣告變數,這宣告方式,會被提升,但裡面的函式內容不可使用

先顯示fun這個函式,再來執行fun(‘text1’),最後底下使用函式表達式來宣告他的內容

console.log(fun); // undefined

fun('text'); // fun is not a function

var fun = function (value) {
     console.log('顯示fun的內容' + value)
}

首先顯示fun函式的地方表示,函式被宣告(已經在記憶體佔位置),但一樣找不到內容

再來執行fun(‘text’),這裡表示找不到是因為這裡只有宣告被提升,但整個函式並沒有被建立

function declaration 函式陳述式

這種函式宣告方式會將function擺前面,而這個函式特別的地方在於,連同函式陳述的內容都被先存到記憶體裡面了

同樣先顯示fun這個函式,再來執行fun(‘text1’),最後底下使用函式陳述式來宣告他的內容

console.log(fun); 
// ƒ fun(value) {
//     console.log('顯示fun的內容' + value)
// }

fun('text'); 
//顯示fun的內容text
function fun(value) {
console.log('顯示fun的內容' + value)
}

首先可以看到整個函式早在程式執行前,就已經被存入記憶體了

所以在顯示的時候顯示整個函式內容

當然執行的時候就可以順利執行函式

宣告let跟const的Hoisting

這裡直接講結論,let跟const會被提升的,但表現形式跟var完全不一樣,差在var宣告的部分會被賦予undefined。let跟const被宣告時也會給予記憶體位置,但是只要還沒被賦值,就不可以被使用

直接顯示三個變數 textVar、 textlet 、textConst ,並在下面分別用var、let、const宣告

console.log(textVar) //undefined
console.log(textlet) //Cannot access 'textLet' before initialization
console.log(textConst) //Cannot access 'textConst' before initialization
var textVar
let textlet = 1
const textConst = 2

這裡可以看到,在下面宣告了三個變數,其實都有在記憶體先佔空間,但是這裡出現的錯誤是”初始化前無法使用”而不是找不到,所以這裡let跟const的規則不太一樣

總結

我們知道了Hoisting的一些規則之後,其實我們很少碰到,但當然詳細還可以繼續探討為什麼要有Hoisting,我稍微看了一下有人提到,就是可以讓函式可以上下互相呼叫,其他還有更深入的探討Hoisting的運作,並且透過運作了解為什麼let跟const必須被初始化才能使用,就留到下一篇文章去了解

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *