摘要:每一個執(zhí)行上下文可以訪問的對象包括自身的作用域和父執(zhí)行上下文的作用域和父父執(zhí)行上下文作用域直到全局作用域,這就產(chǎn)生了作用域鏈。語句結(jié)束后,作用域鏈恢復(fù)正常。
0、自己理解
代碼執(zhí)行或函數(shù)調(diào)用生成執(zhí)行上下文(只有當前執(zhí)行上下文有執(zhí)行權(quán)),該執(zhí)行上下文內(nèi)只能訪問當前執(zhí)行上下文的變量、函數(shù)和上一級執(zhí)行上下文中的變量、函數(shù),激活下一個執(zhí)行上下文的時候執(zhí)行權(quán)轉(zhuǎn)移到新的執(zhí)行上下文,形成執(zhí)行上下文棧。
作用域是當前執(zhí)行上下文中能訪問的變量、函數(shù)的集合,執(zhí)行上下文中只能訪問當前作用域和其上執(zhí)行上下文的作用域,由此形成作用域鏈
1、執(zhí)行上下文(棧)每一次代碼執(zhí)行和函數(shù)調(diào)用都會產(chǎn)生一個執(zhí)行環(huán)境,稱為執(zhí)行上下文(context stack)。
一個執(zhí)行上下文caller又可以激活(調(diào)用)另一個執(zhí)行上下文callee,這時caller會暫停自身的執(zhí)行把控制權(quán)交給callee進入callee的執(zhí)行上下文,callee執(zhí)行完畢后將控制權(quán)交回caller,callee可以用return或者拋出Exception來結(jié)束自己的執(zhí)行。
多個執(zhí)行上下文會形成執(zhí)行上下文棧,最頂層是當前執(zhí)行上下文,底層是全局執(zhí)行上下文。
作用域(scope chain)是每一個執(zhí)行上下文自身持有的活動對象的集合,如在本執(zhí)行上下文中聲明的變量和函數(shù)以及方法參數(shù)傳入的對象。
每一個執(zhí)行上下文可以訪問的對象包括自身的作用域和父執(zhí)行上下文的作用域和父父執(zhí)行上下文作用域直到全局作用域,這就產(chǎn)生了作用域鏈。作用域鏈的用途是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。
作用域鏈的工作原理跟原型鏈十分相似:如果本身的作用域中查找不到標識符,那么就查找父作用域,直到頂層。
目前假設(shè)作用域的聯(lián)動是用的__parent__對象,它指向作用域鏈的下一個對象。(在ES5中,確實有一個outer鏈接)
全局上下文的作用域包含Object.prototype中的對象,with和catch會改變作用域鏈,在with中,查詢__parent__之前會先去查詢__proto__,會使作用域鏈增大。
2.1 作用域鏈中的名稱解析順序javascript中一個名字(name)以四種方式進入作用域(scope),其優(yōu)先級順序如下:
語言內(nèi)置:所有的作用域中都有 this 和 arguments 關(guān)鍵字
形式參數(shù):函數(shù)的參數(shù)在函數(shù)作用域中都是有效的
函數(shù)聲明:形如function foo() {}
變量聲明:形如var bar;
名字聲明的優(yōu)先級如上所示,也就是說如果一個變量的名字與函數(shù)的名字相同,那么函數(shù)的名字會覆蓋變量的名字,無論其在代碼中的順序如何;形式參數(shù)會覆蓋變量聲明。但名字的初始化卻是按其在代碼中書寫的順序進行的,不受以上優(yōu)先級的影響。
(function(){ var foo; console.log(typeof foo); //function function foo(){} foo = "foo"; console.log(typeof foo); //string })();
如果形參中有多個同名變量,那么最后一個同名參數(shù)會覆蓋其他同名參數(shù),即使最后一個同名參數(shù)未定義;以上的名字解析優(yōu)先級存在例外,比如可以覆蓋語言內(nèi)置的名字arguments。
2.2 with改變作用域鏈with語句主要用來臨時擴展作用域鏈,將語句中的對象添加到作用域的頭部。
person={name:"yhb",age:22,height:175,wife:{name:"lwy",age:21}}; with(person.wife){ console.log(name); }
with語句將person.wife添加到當前作用域鏈的頭部,所以輸出的就是lwy。with語句結(jié)束后,作用域鏈恢復(fù)正常。
3、二維作用域鏈查找源于ECMAScript的原型特性。如果一個屬性在對象中沒有直接找到,查詢將在原型鏈中繼續(xù)。即常說的二維鏈查找。
作用域鏈環(huán)節(jié);
每個作用域鏈-深入到原型鏈環(huán)節(jié)
網(wǎng)上的帖子大多深淺不一,甚至有些前后矛盾,在下的文章都是學(xué)習(xí)過程中的總結(jié),如果發(fā)現(xiàn)錯誤,歡迎留言指出~
參考:
1、執(zhí)行上下文(棧)/作用域(鏈)/with
2、Js 作用域與作用域鏈與執(zhí)行上下文不得不說的故事
PS:歡迎大家關(guān)注我的公眾號【前端下午茶】,一起加油吧~
另外可以加入「前端下午茶交流群」微信群,長按識別下面二維碼即可加我好友,備注加群,我拉你入群~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92024.html
摘要:在之前我們根絕對象的原型說過了的原型鏈,那么同樣的萬物皆對象,函數(shù)也同樣存在這么一個鏈式的關(guān)系,就是函數(shù)的作用域鏈作用域鏈首先先來回顧一下之前講到的原型鏈的尋找機制,就是實例會先從本身開始找,沒有的話會一級一級的網(wǎng)上翻,直到頂端沒有就會報一 在之前我們根絕對象的原型說過了js的原型鏈,那么同樣的js 萬物皆對象,函數(shù)也同樣存在這么一個鏈式的關(guān)系,就是函數(shù)的作用域鏈 作用域鏈 首先先來回...
摘要:開篇作用域是每種計算機語言最重要的基礎(chǔ)之一,因此要想深入的學(xué)習(xí)作用域和作用域鏈就是個繞不開的話題。這樣由多個執(zhí)行上下文的變量對象構(gòu)成的鏈表就叫做作用域鏈。這時候執(zhí)行上下文的作用域鏈,我們命名為至此,作用域鏈創(chuàng)建完畢。 開篇 作用域是每種計算機語言最重要的基礎(chǔ)之一,因此要想深入的學(xué)習(xí)JavaScript,作用域和作用域鏈就是個繞不開的話題。 在《深入學(xué)習(xí)js之—-執(zhí)行上下文?!分形覀兲岬?..
摘要:思考題在深入學(xué)習(xí)之詞法作用域和動態(tài)作用域中,提出這樣一道思考題思考題一思考題二兩段代碼都會打印但是還是有些許差異的,本文就詳細的解析執(zhí)行上下文棧和執(zhí)行上下文的具體變化過程。 在《深入學(xué)習(xí)js之——執(zhí)行上下文?!分姓f過,當JavaScript代碼執(zhí)行一段可執(zhí)行代碼(executable code)時,會創(chuàng)建對應(yīng)的執(zhí)行上下文(execution context) 對于每一個執(zhí)行上下文,都有...
摘要:執(zhí)行上下文棧首先我們先了解一下什么是執(zhí)行上下文棧。那么隨著我們的執(zhí)行上下文數(shù)量的增加,引擎又如何去管理這些執(zhí)行上下文呢這時便有了執(zhí)行上下文棧。這樣由多個執(zhí)行上下文的變量對象構(gòu)成的鏈表就叫做作用域鏈。 執(zhí)行上下文棧 首先我們先了解一下什么是執(zhí)行上下文棧(Execution context stack)。 showImg(https://segmentfault.com/img/remot...
摘要:執(zhí)行上下文作用域鏈和內(nèi)部機制一執(zhí)行上下文執(zhí)行上下文是代碼的執(zhí)行環(huán)境,它包括的值變量對象和函數(shù)。創(chuàng)建作用域鏈一旦可變對象創(chuàng)建完,引擎就開始初始化作用域鏈。 執(zhí)行上下文、作用域鏈和JS內(nèi)部機制(Execution context, Scope chain and JavaScript internals) 一、執(zhí)行上下文 執(zhí)行上下文(Execution context EC)是js代碼的執(zhí)...
閱讀 2849·2021-10-13 09:48
閱讀 3851·2021-10-13 09:39
閱讀 3628·2021-09-22 16:04
閱讀 1872·2021-09-03 10:48
閱讀 875·2021-08-03 14:04
閱讀 2386·2019-08-29 15:18
閱讀 3443·2019-08-26 12:19
閱讀 2899·2019-08-26 12:08