談?wù)刯avascript中的變量提升還有函數(shù)提升

在很多面試題中,經(jīng)常會看到關(guān)于變量提升,還有函數(shù)提升的題目,所以我就寫一篇自己理解之后的隨筆,方便之后的查閱和復(fù)習(xí)。

首先舉個例子

foo();//undefined
function foo(){
    console.log(a);//undefined
    var a = 10;
}

上面的例子中,foo()函數(shù)的聲明在調(diào)用之后,但是還是會輸出函數(shù)中的結(jié)果。在foo()函數(shù)的內(nèi)部,變量a的聲明之前就調(diào)用了,但是系統(tǒng)會輸出undefined,而不會報錯,這里面就涉及到了變量提升還有函數(shù)提升,為什么會出現(xiàn)這樣的情況呢,先來了解幾個重要的概念,就可以解開這個謎底了。

一、什么是執(zhí)行上下文

每次當(dāng)控制器轉(zhuǎn)到可執(zhí)行代碼的時候,就會進(jìn)入一個可執(zhí)行上下文。執(zhí)行上下文可以理解為當(dāng)前代碼的執(zhí)行環(huán)境,它會形成一個作用域。

一個執(zhí)行上下文的生命周期

執(zhí)行上下文.PNG

從圖中可以看出,一個執(zhí)行上下文的生命周期包括創(chuàng)建執(zhí)行兩個階段。
1、第一個階段中做的工作有:

  • 生成變量對象
  • 建立作用域鏈
  • 確定this的指向

2、第二個階段中做的工作有:

  • 變量賦值
  • 函數(shù)引用
  • 執(zhí)行其他代碼

到這里還不能解析為什么會有變量提升和函數(shù)提升的過程,那么我們接下來再深入執(zhí)行上下文中的創(chuàng)建階段中的生成變量對象的過程

什么是變量對象

在很多面試題中,會考到變量對象和活動對象的區(qū)別,其實活動對象和變量對象是同一個對象,只是處于執(zhí)行上下文的不同生命周期而已,活動對象處于執(zhí)行階段。

變量對象.PNG

從圖中可以看出,在生成變量對象的過程中,執(zhí)行的操作有三步
1、創(chuàng)建arguments對象
2、檢查functfen函數(shù)聲明創(chuàng)建屬性
3、檢查var變量聲明創(chuàng)建屬性

所以在了解完執(zhí)行上下文和變量對象后,就可以分析一下我們的問題了。
當(dāng)我們執(zhí)行第一句話的時候foo(),javascript引擎會創(chuàng)建一個執(zhí)行上下文testEc,并且生成一個變量對象VO,首先創(chuàng)建argument對象,然后檢查function函數(shù)聲明并且創(chuàng)建一個屬性,所以就生成了如下的vo對象
創(chuàng)建過程
testEC = {
    // 變量對象
    VO: {},
    scopeChain: {},
    this: {}
}

// 因為本文暫時不詳細(xì)解釋作用域鏈和this,所以把變量對象專門提出來說明

// VO 為 Variable Object的縮寫,即變量對象
VO = {
    arguments: {...},  //注:在瀏覽器的展示中,函數(shù)的參數(shù)可能并不是放在arguments對象中,這里為了方便理解,我做了這樣的處理
    foo: <foo reference>  // 表示foo的地址引用
    a: undefined
}
變量提升也是同樣的道理。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容