摘要:開篇作用域是每種計算機語言最重要的基礎(chǔ)之一,因此要想深入的學(xué)習(xí)作用域和作用域鏈就是個繞不開的話題。這樣由多個執(zhí)行上下文的變量對象構(gòu)成的鏈表就叫做作用域鏈。這時候執(zhí)行上下文的作用域鏈,我們命名為至此,作用域鏈創(chuàng)建完畢。
開篇
作用域是每種計算機語言最重要的基礎(chǔ)之一,因此要想深入的學(xué)習(xí)JavaScript,作用域和作用域鏈就是個繞不開的話題。
在《深入學(xué)習(xí)js之—-執(zhí)行上下文棧》中我們提到過,當(dāng)JavaScript代碼執(zhí)行一段可執(zhí)行代碼(executable code)時,會創(chuàng)建對應(yīng)的執(zhí)行上下文(execution context)。
對于每個執(zhí)行上下文,都有三個重要屬性:
變量對象(Variable object,VO)
作用域鏈(Scope chain)
this
今天重點聊聊作用域鏈。
作用域細(xì)說作用域鏈之前,我們首先來聊聊作用域,簡單的說,作用域就是變量與函數(shù)的可訪問范圍,即作用域控制著變量與函數(shù)的可見性和生命周期。
在JavaScript中,變量的作用域有全局作用域和局部作用域兩種(局部作用域又稱為函數(shù)作用域)。
作用域鏈代碼在當(dāng)查找變量的時候,會先從當(dāng)前上下文的變量對象中查找,如果沒有找到,就會從父級(詞法層面上的父級)執(zhí)行上下文的變量對象中查找,一直找到全局上下文的變量對象,也就是全局對象。
這樣由多個執(zhí)行上下文的變量對象構(gòu)成的鏈表就叫做作用域鏈。
下面,讓我們以一個函數(shù)的創(chuàng)建和激活兩個時期來講解作用域鏈?zhǔn)侨绾蝿?chuàng)建和變化的。
函數(shù)創(chuàng)建在《深入學(xué)習(xí)js之——詞法作用域和動態(tài)作用域》中講到,函數(shù)的作用域在函數(shù)定義的時候就決定了——即JavaScript采用的是靜態(tài)作用域。
這是因為函數(shù)有一個內(nèi)部屬性 [[scope]],當(dāng)函數(shù)創(chuàng)建的時候,就會保存所有父變量對象到其中,你可以理解 [[scope]] 就是所有父變量對象的層級鏈,但是注意:[[scope]] 并不代表完整的作用域鏈!
舉個例子:
function foo(){ function bar(){ ... } }
函數(shù)創(chuàng)建時,各自的[[scope]]為:
foo.[[scope]] = [ globalContext.VO ]; bar.[[scope]] = [ fooContext.AO, globalContext.VO ];函數(shù)激活
當(dāng)函數(shù)激活時,進入函數(shù)上下文,創(chuàng)建 VO/AO 后,就會將活動對象添加到作用鏈的前端。
這時候執(zhí)行上下文的作用域鏈,我們命名為 Scope:
Scope = [AO].concat([[Scope]]);
至此,作用域鏈創(chuàng)建完畢。
通過例子深刻理解以下面的例子為例,結(jié)合著之前講的變量對象和執(zhí)行上下文棧,我們來總結(jié)一下函數(shù)執(zhí)行上下文中作用域鏈和變量對象的創(chuàng)建過程:
var scope = "global scope"; function checkscope(){ var scope2 = "local scope"; return scope2; } checkscope();
執(zhí)行過程如下:
1.checkscope 函數(shù)被創(chuàng)建,保存作用域鏈到 內(nèi)部屬性[[scope]];
checkscope.[[scope]] = [ globalContext.VO ];
2.執(zhí)行 checkscope 函數(shù),創(chuàng)建 checkscope 函數(shù)執(zhí)行上下文,checkscope 函數(shù)執(zhí)行上下文被壓入執(zhí)行上下文棧;
ECStack = [ checkscopeContext, globalContext ];
3.checkscope 函數(shù)并不立刻執(zhí)行,開始做準(zhǔn)備工作,第一步:復(fù)制函數(shù)[[scope]]屬性創(chuàng)建作用域鏈;
checkscopeContext = { Scope: checkscope.[[scope]], }
4.第二步:用 arguments 創(chuàng)建活動對象,隨后初始化活動對象,加入形參、函數(shù)聲明、變量聲明;
checkscopeContext = { AO: { arguments: { length: 0 }, scope2: undefined }, Scope: checkscope.[[scope]], }
5.第三步:將活動對象壓入 checkscope 作用域鏈頂端;
checkscopeContext = { AO: { arguments: { length: 0 }, scope2: undefined }, Scope: [AO, [[Scope]]] }
6.準(zhǔn)備工作做完,開始執(zhí)行函數(shù),隨著函數(shù)的執(zhí)行,修改 AO 的屬性值;
checkscopeContext = { AO: { arguments: { length: 0 }, scope2: "local scope" }, Scope: [AO, [[Scope]]] }
7.查找到 scope2 的值,返回后函數(shù)執(zhí)行完畢,函數(shù)上下文從執(zhí)行上下文棧中彈出;
ECStack = [ globalContext ];參考:
《JavaScript深入之作用域鏈》
《深入了解JavaScript,從作用域鏈開始》
歡迎添加我的個人微信討論技術(shù)和個體成長。
歡迎關(guān)注我的個人微信公眾號——指尖的宇宙,更多優(yōu)質(zhì)思考干貨
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/102045.html
摘要:思考題在深入學(xué)習(xí)之詞法作用域和動態(tài)作用域中,提出這樣一道思考題思考題一思考題二兩段代碼都會打印但是還是有些許差異的,本文就詳細(xì)的解析執(zhí)行上下文棧和執(zhí)行上下文的具體變化過程。 在《深入學(xué)習(xí)js之——執(zhí)行上下文棧》中說過,當(dāng)JavaScript代碼執(zhí)行一段可執(zhí)行代碼(executable code)時,會創(chuàng)建對應(yīng)的執(zhí)行上下文(execution context) 對于每一個執(zhí)行上下文,都有...
摘要:在中的應(yīng)用采用詞法作用域,也就是靜態(tài)作用域。那什么又是詞法作用域或者靜態(tài)作用域呢請繼續(xù)往下看靜態(tài)作用域與動態(tài)作用域因為采用的是詞法作用域函數(shù)的作用域在函數(shù)定義的時候就決定了。 開篇 當(dāng)我們在開始學(xué)習(xí)任何一門語言的時候,都會接觸到變量的概念,變量的出現(xiàn)其實是為了解決一個問題,為的是存儲某些值,進而,存儲某些值的目的是為了在之后對這個值進行訪問或者修改,正是這種存儲和訪問變量的能力將狀態(tài)給...
摘要:深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧變量對象作用域鏈?zhǔn)侨绾巫兓摹G把栽谏钊胫畧?zhí)行上下文棧中講到,當(dāng)代碼執(zhí)行一段可執(zhí)行代碼時,會創(chuàng)建對應(yīng)的執(zhí)行上下文。 JavaScript深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的demo為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧、變量對象、作用域鏈?zhǔn)侨绾巫兓摹?前言 在《Jav...
摘要:本期推薦文章從作用域鏈談閉包,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。推薦理由這是一篇譯文,深入淺出圖解作用域鏈,一步步深入介紹閉包。作用域鏈的頂端是全局對象,在全局環(huán)境中定義的變量就會綁定到全局對象中。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周開始前端進階的第二期,本周的主題是作用域閉包,今天是第6天。 本...
摘要:閉包面試題解由于作用域鏈機制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個值,這引起的一個副作用就是如果內(nèi)部函數(shù)在一個循環(huán)中,那么變量的值始終為最后一個值。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...
閱讀 2310·2021-11-22 12:01
閱讀 1983·2021-11-12 10:34
閱讀 4508·2021-09-22 15:47
閱讀 2827·2019-08-30 15:56
閱讀 2860·2019-08-30 15:53
閱讀 2397·2019-08-30 13:53
閱讀 3370·2019-08-29 15:35
閱讀 3119·2019-08-29 12:27