web前端之javascript變數提升詳解
js變數提升
對於大多數js開發者來說,變數提升可以說是一個非常常見的問題,但是可能很多人對其不是特別的瞭解。所以在此,我想來講一講。
先從一個簡單的例子來入門:
你覺得以上的程式碼會輸出什麼?是輸出undefined嗎?如果是按照程式的自上而下執行的話,那麼這一段程式碼確實是輸出undefined。然而,javascript並不是嚴格的自上而下執行的語言。
這一段程式碼的輸出結果是2,是不是感到很意外?為什麼會這樣呢?這個問題的關鍵就在於變數提升(hoisting)。它會將當前作用域的所有變數的宣告提升到程式的頂部,因此上面的程式碼其實等價於以下程式碼。這樣是不是就很簡單明瞭了。
那麼接下來,我們再來看這個例子。
你覺得以上的程式碼會輸出什麼?是直接報ReferenceError嗎?還是輸出2呢?
其實以上程式碼會輸出undefined。為什麼呢?我們之前說過,js會將變數的宣告提升到頂部,可是賦值語句並不會提升。對於js來說,其實var a = 2是分為兩步的:
var a;
a = 2;
而js只會將第一步提升到頂部,所以上面的語句等價於:
為什麼有變數提升
那麼為什麼會出現變數提升這個現象呢?
js和其他語言一樣,都要經歷編譯和執行階段。而js在編譯階段的時候,會蒐集所有的變數宣告並且提前宣告變數,而其他的語句都不會改變他們的順序,因此,在編譯階段的時候,第一步就已經執行了,而第二步則是在執行階段執行到該語句的時候才執行。
變數宣告
js的變數宣告其實大體上可以分為三種:var宣告、let與const宣告和函式宣告。
函式宣告與其他宣告一起出現的時候,就可能會引起一些困擾。我們來看下面的例子。
當出現多個函式宣告,那怎麼辦呢?以上程式碼輸出結果為2。因為有多個函式宣告的時候,是由最後面的函式宣告來替代前面的。
想必經歷了以上的例子,你應該已經對變數宣告已經有一定的瞭解了。那麼我再來出一道題目來測試下。
這道題目是不是非常簡單啊?這道題和上面的第二道例子其實是一樣的。var foo = function() {}這種格式我們叫做函式表示式。
它其實也是分為兩部分,一部分是var foo,而一部分是foo = function() {},參照例2,我們可以知道,這道題的結果應該是報了TypeError(因為foo宣告但未賦值,因此foo是undefined)。
上面我們提到了var宣告,函式宣告,那麼接下來我們來講講let和const宣告呢。
總結
那麼接下來我們來總結一下。
js會將變數的宣告提升到js頂部執行,因此對於這種語句:var a = 2;其實上js會將其分為var a;和a = 2;兩部分,並且將var a這一步提升到頂部執行。
變數提升的本質其實是由於js引擎在編譯的時候,就將所有的變數聲明瞭,因此在執行的時候,所有的變數都已經完成宣告。
當有多個同名變數宣告的時候,函式宣告會覆蓋其他的宣告。如果有多個函式宣告,則是由最後的一個函式宣告覆蓋之前所有的宣告。
最後:
“相信有很多想學前端的小夥伴,今年年初我花了一個月整理了一份最適合2018年學習的web前端乾貨,從最基礎的HTML+CSS+JS到移動端HTML5等都有整理,送給每一位前端小夥伴,53763,1707這裡是小白聚集地,歡迎初學和進階中的小夥伴。”