摘要:例如在上面的代碼中,執(zhí)行語句時(shí),作用域鏈的最頂端是臨時(shí)添加的對(duì)象,因此可以直接訪問對(duì)象的屬性獲取值。在執(zhí)行語句時(shí),會(huì)創(chuàng)建一個(gè)新的變量對(duì)象該對(duì)象中包含被拋出的錯(cuò)誤對(duì)象,并添加到作用域鏈的頂端。
執(zhí)行環(huán)境(也就是常說的上下文)和作用域是js中很基礎(chǔ)也很重要的概念, 但在很多時(shí)候,特別是看其他的文檔的時(shí)候,卻容易混淆概念,這篇文章試著梳理下執(zhí)行環(huán)境和作用域的概念。
1、執(zhí)行環(huán)境
執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了它們各自的行為。每個(gè)執(zhí)行環(huán)境都有一個(gè)相關(guān)聯(lián)的變量對(duì)象,這個(gè)對(duì)象里面保存了環(huán)境中定義的所有變量和函數(shù)。這個(gè)變量對(duì)象在編寫代碼是不能訪問的(除了最外層的window對(duì)象),只有解析器在后臺(tái)處理才能使用。
執(zhí)行環(huán)境可以分成兩種:全局執(zhí)行環(huán)境和函數(shù)執(zhí)行環(huán)境。在執(zhí)行js代碼之前,默認(rèn)都會(huì)創(chuàng)建一個(gè)全局的執(zhí)行環(huán)境,與之關(guān)聯(lián)的是window對(duì)象,里面保存了所有全局變量和函數(shù),直到頁面關(guān)閉時(shí)才銷毀。而當(dāng)執(zhí)行某個(gè)函數(shù)時(shí),會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象,并把這個(gè)對(duì)象作為與該函數(shù)的執(zhí)行環(huán)境關(guān)聯(lián)的變量對(duì)象,從而創(chuàng)建出函數(shù)的執(zhí)行環(huán)境。函數(shù)的執(zhí)行環(huán)境在函數(shù)執(zhí)行完之后,就會(huì)被銷毀。
另外,需要提一句的是:在活動(dòng)對(duì)象剛被創(chuàng)建時(shí),對(duì)象中只有arguments對(duì)象一個(gè)屬性。
2、作用域
了解執(zhí)行環(huán)境,就可以來說作用域了。
在js中,執(zhí)行環(huán)境是用環(huán)境棧來管理的。最底層的是全局執(zhí)行環(huán)境,當(dāng)執(zhí)行到一個(gè)函數(shù), 函數(shù)的執(zhí)行環(huán)境就會(huì)被推入到環(huán)境棧中。如果在函數(shù)中繼續(xù)執(zhí)行函數(shù),那么內(nèi)部函數(shù)的執(zhí)行環(huán)境就繼續(xù)被推入環(huán)境棧。例如下面的代碼:
var name = "window"; outer(); function outer(){ var name = "outer"; inner(); //函數(shù)內(nèi)部的函數(shù) function inner(){ var name = "inner"; console.log(name); } }
對(duì)應(yīng)的環(huán)境棧如下:
環(huán)境棧中的變量對(duì)象,從上到下就組成一條作用域鏈, 用來保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。解析標(biāo)識(shí)符時(shí),就沿著作用域鏈一級(jí)一級(jí)地搜索,也就在環(huán)境棧中從上向下一個(gè)個(gè)對(duì)象搜索,直到找到標(biāo)識(shí)符,就返回,否則就報(bào)錯(cuò)。例如,上面的代碼,執(zhí)行后會(huì)輸出‘inner’,當(dāng)把inner函數(shù)中的定義變量語句注釋之后就輸出‘outer’。
2、延長(zhǎng)作用域鏈
在兩種情況下,雖然不是在執(zhí)行函數(shù),但也會(huì)在作用域鏈的前端臨時(shí)增加一個(gè)變量對(duì)象:
try-catch語句的catch塊
with 語句
在執(zhí)行with 語句時(shí),會(huì)將指定的對(duì)象添加到作用域鏈中。例如:
function getHost() { var res = ""; with(location){ res = host; } return res; }
在上面的代碼中,執(zhí)行with語句時(shí),作用域鏈的最頂端是臨時(shí)添加的location對(duì)象,因此可以直接訪問location對(duì)象的host屬性獲取值。
在執(zhí)行catch語句時(shí),會(huì)創(chuàng)建一個(gè)新的變量對(duì)象(該對(duì)象中包含被拋出的錯(cuò)誤對(duì)象),并添加到作用域鏈的頂端。正因?yàn)檫@個(gè)原因,在js的編程中,如果不是必要的,不建議在代碼中使用try-catch語句塊。
備注:
在第一個(gè)例子中,我們把inner函數(shù)定義在outer函數(shù)的內(nèi)部,如果是定義在outer函數(shù)外部呢?會(huì)不會(huì)有什么不同?原因是什么?
寫在最后:
如果覺得我寫的文章對(duì)你有幫助,歡迎掃碼關(guān)注我的公眾號(hào):海痕筆記
微信號(hào):haihenbiji
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/82221.html
摘要:所以,全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。講到這里,可能你已經(jīng)對(duì)執(zhí)行環(huán)境執(zhí)行環(huán)境對(duì)象變量對(duì)象作用域作用域鏈的理解已經(jīng)他們之間的關(guān)系有了一個(gè)較清晰的認(rèn)識(shí)。 JavaScript中的執(zhí)行環(huán)境、作用域、作用域鏈、閉包一直是一個(gè)非常有意思的話題,很多博主和大神都分享過相關(guān)的文章。這些知識(shí)點(diǎn)不僅比較抽象,不易理解,更重要的是與這些知識(shí)點(diǎn)相關(guān)的問題在面試中高頻出現(xiàn)。之前我也看過...
摘要:當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中。在函數(shù)執(zhí)行完后,棧將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。執(zhí)行環(huán)境可以分為創(chuàng)建執(zhí)行銷毀三個(gè)階段。在這個(gè)階段,作用域鏈會(huì)被初始化,的值也會(huì)被最終確定。 執(zhí)行環(huán)境 執(zhí)行環(huán)境中定義了變量和函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了他們各自的行為。 當(dāng)JavaScript解釋器初始化執(zhí)行代碼時(shí),它首先默認(rèn)進(jìn)入全局執(zhí)行環(huán)境,從此刻開始,函數(shù)的每...
摘要:作用域與作用域鏈每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境。這是初步了解作用域,如想更深入了解作用域,請(qǐng)看下面鏈接作用域原理作用域鏈由一道題圖解的作用域或者看權(quán)威指南和高級(jí)程序設(shè)計(jì) 本文是我學(xué)習(xí)JavaScript作用域整理的筆記,如有不對(duì),請(qǐng)多指出。 作用域 一個(gè)變量的作用域是程序源代碼中定義這個(gè)變量的區(qū)域。 而在ES5中只分為全局作用域和函數(shù)作用域,也就是說for,if,while等語句是不會(huì)創(chuàng)建...
摘要:全局執(zhí)行環(huán)境的變量對(duì)象始終是作用域鏈中的最后一個(gè)變量對(duì)象。綜上,每個(gè)函數(shù)對(duì)應(yīng)一個(gè)執(zhí)行環(huán)境,每個(gè)執(zhí)行環(huán)境對(duì)應(yīng)一個(gè)變量對(duì)象,而多個(gè)變量對(duì)象構(gòu)成了作用域鏈,如果當(dāng)前執(zhí)行環(huán)境是函數(shù),那么其活動(dòng)對(duì)象在作用域鏈的前端。 1.幾個(gè)概念 先說幾個(gè)概念:函數(shù)、執(zhí)行環(huán)境、變量對(duì)象、作用域鏈、活動(dòng)對(duì)象。這幾個(gè)東東之間有什么關(guān)系呢,往下看~ 函數(shù) 函數(shù)大家都知道,我想說的是,js中,在函數(shù)內(nèi)部有兩個(gè)特殊...
摘要:執(zhí)行上下文環(huán)境然后將執(zhí)行上下文環(huán)境壓棧,設(shè)置為活動(dòng)狀態(tài)當(dāng)前唯一然后執(zhí)行到第行,調(diào)用函數(shù)。有閉包存在時(shí),一個(gè)作用域存在兩個(gè)上下文環(huán)境也是有的。這就是作用域鏈。 本文參考引自:深入理解javascript原型和閉包(完結(jié))不得不說,這個(gè)系列文章是真的給人恍然頓悟的感覺,寫的非常好,強(qiáng)烈推薦。感謝大佬! 執(zhí)行上下文 函數(shù)每調(diào)用一次,都會(huì)產(chǎn)生一個(gè)新的執(zhí)行上下文環(huán)境。因?yàn)椴煌恼{(diào)用可能就有不同的...
摘要:講作用域鏈?zhǔn)紫纫獜淖饔糜蛑v起,下面是百度百科里對(duì)作用域的定義作用域在許多程序設(shè)計(jì)語言中非常重要。原文出處談?wù)務(wù)Z法里一些難點(diǎn)問題二 3) 作用域鏈相關(guān)的問題 作用域鏈?zhǔn)莏avascript語言里非常紅的概念,很多學(xué)習(xí)和使用javascript語言的程序員都知道作用域鏈?zhǔn)抢斫鈐avascript里很重要的一些概念的關(guān)鍵,這些概念包括this指針,閉包等等,它非常紅的另一個(gè)重要原因就...
閱讀 3591·2021-11-04 16:06
閱讀 3589·2021-09-09 11:56
閱讀 854·2021-09-01 11:39
閱讀 906·2019-08-29 15:28
閱讀 2300·2019-08-29 15:18
閱讀 837·2019-08-29 13:26
閱讀 3338·2019-08-29 13:22
閱讀 1051·2019-08-29 12:18