有玩天津时时彩平台:javascript變量提升詳解

發布日期:2019-07-16

吉林快三全天计划106 www.gcgzhn.com.cn js變量提升

對于大多數js開發者來說,變量提升可以說是一個非常常見的問題,但是可能很多人對其不是特別的了解。所以在此,我想來講一講。

先從一個簡單的例子來入門:

a = 2var aconsole.log(a)

你覺得以上的代碼會輸出什么?是輸出undefined嗎?如果是按照程序的自上而下執行的話,那么這一段代碼確實是輸出undefined。然而,javascript并不是嚴格的自上而下執行的語言。

這一段代碼的輸出結果是2,是不是感到很意外?為什么會這樣呢?這個問題的關鍵就在于變量提升(hoisting)。它會將當前作用域的所有變量的聲明提升到程序的頂部,因此上面的代碼其實等價于以下代碼。這樣是不是就很簡單明了了。

var aa = 2console.log(a)

那么接下來,我們再來看這個例子。

console.log(a)var a = 2

你覺得以上的代碼會輸出什么?是直接報ReferenceError嗎?還是輸出2呢?

其實以上代碼會輸出undefined。為什么呢?我們之前說過,js會將變量的聲明提升到頂部,可是賦值語句并不會提升。對于js來說,其實var a = 2是分為兩步的:

    var aa = 2

而js只會將第一步提升到頂部,所以上面的語句等價于:

var aconsole.log(a)a = 2

為什么有變量提升

那么為什么會出現變量提升這個現象呢?

js和其他語言一樣,都要經歷編譯和執行階段。而js在編譯階段的時候,會搜集所有的變量聲明并且提前聲明變量,而其他的語句都不會改變他們的順序,因此,在編譯階段的時候,第一步就已經執行了,而第二步則是在執行階段執行到該語句的時候才執行。

變量聲明

js的變量聲明其實大體上可以分為三種:var聲明、let與const聲明和函數聲明。

函數聲明與其他聲明一起出現的時候,就可能會引起一些困擾。我們來看下面的例子。

foo()function foo() { console.log("foo")}var foo = 2

你覺得上面會輸出什么?TypeError嗎?其實輸出的結果是foo。這就引出了我們的問題了,當函數聲明與其他聲明一起出現的時候,是以誰為準呢?答案就是,函數聲明高于一切,畢竟函數是js的第一公民。

那么,下面的例子呢?

foo()function foo() { console.log("1")}function foo() { console.log("2")}

當出現多個函數聲明,那怎么辦呢?以上代碼輸出結果為2。因為有多個函數聲明的時候,是由最后面的函數聲明來替代前面的。

想必經歷了以上的例子,你應該已經對變量聲明已經有一定的了解了。那么我再來出一道題目來測試下。

foo()var foo = function() { console.log("foo")}

這道題目是不是非常簡單???這道題和上面的第二道例子其實是一樣的。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引擎在編譯的時候,就將所有的變量聲明了,因此在執行的時候,所有的變量都已經完成聲明。當有多個同名變量聲明的時候,函數聲明會覆蓋其他的聲明。如果有多個函數聲明,則是由最后的一個函數聲明覆蓋之前所有的聲明。