資源描述:
《javascript執(zhí)行環(huán)境及作用域詳解_javascript技巧》由會員上傳分享,免費在線閱讀,更多相關(guān)內(nèi)容在工程資料-天天文庫。
1、javascript執(zhí)行環(huán)境及作用域詳解最近在重讀《javascript高級程序設(shè)計3》,覺得應(yīng)該寫一些博客記錄一下學習的一些知識,不然都忘光啦。今天??偨Y(jié)的是js執(zhí)行環(huán)境和作用域。首先來說一下執(zhí)行環(huán)境一、執(zhí)行環(huán)境書上概念,執(zhí)行環(huán)境定義了變量或者函數(shù)冇權(quán)訪問的其他數(shù)據(jù),決定了他們各口的行為。每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象。環(huán)境中定義的所有變量和函數(shù)都保存在這個對象屮。雖然我們在編寫代碼的吋候無法訪問這個對象,但解析器在處理數(shù)據(jù)時會在后臺用到它。執(zhí)行環(huán)境是一個概念,一種機制,它定義了變量或函數(shù)是否有權(quán)訪問其他數(shù)據(jù)在javascript
2、中,可執(zhí)行的JavaScript代碼分三種類型:1.GlobalCode,即全局的、不在任何函數(shù)里面的代碼,例如:一個js文件、嵌入在HTML頁面中的js代碼等。2.EvalCode,即使用eval()函數(shù)動態(tài)執(zhí)行的JS代碼。3.FunctionCode,即用戶自定義函數(shù)中的函數(shù)體JS代碼。跳過EvalCode,只說全局執(zhí)行環(huán)境和函數(shù)執(zhí)行環(huán)境。1、全局環(huán)境:全局環(huán)境是最外圍的一個執(zhí)彳亍環(huán)境。全局執(zhí)彳亍環(huán)境被認為是window對象。因此所有全局變量和函數(shù)都是作為window對象的屈性和方法創(chuàng)建的。代碼載入瀏覽器時,全局執(zhí)行環(huán)境被創(chuàng)建(當我們關(guān)
3、閉網(wǎng)頁或者瀏覽器時全局執(zhí)行環(huán)境才被銷毀)。比如在一個頁面中,第一次載入JS代碼時創(chuàng)建一個全局執(zhí)行環(huán)境。這也是為什么閉包有一個內(nèi)存泄露的缺點。因為閉包屮外部函數(shù)被當成了全局環(huán)境。所以不會被銷毀,一直保存在內(nèi)存中。2、函數(shù)執(zhí)行環(huán)境每個函數(shù)都冇自己的執(zhí)行環(huán)境,當執(zhí)行進入一個函數(shù)時,函數(shù)的執(zhí)行環(huán)境就會被推入一個執(zhí)行環(huán)境棧的頂部并獲取執(zhí)行權(quán)。當這個函數(shù)執(zhí)行完畢,它的執(zhí)行環(huán)境又從這個棧的頂部被刪除,并把執(zhí)行權(quán)并述給之前執(zhí)行環(huán)境。這就是ECMAScript程序中的執(zhí)行流。也可以這樣解讀:當調(diào)用一個JavaScdpt函數(shù)時,該函數(shù)就會進入與該函數(shù)相對應(yīng)的執(zhí)
4、行環(huán)境。如果又調(diào)用了另外一個函數(shù),則又會創(chuàng)建一個新的執(zhí)行環(huán)境,并且在函數(shù)調(diào)用期間執(zhí)行過程都處于該環(huán)境中。當調(diào)用的函數(shù)返冋后,執(zhí)行過程會返回原始執(zhí)行環(huán)境。因而,運行屮的JavaScript代碼就構(gòu)成了一個執(zhí)行環(huán)境棧。當函數(shù)被調(diào)用時函數(shù)的局部環(huán)境被創(chuàng)建(函數(shù)內(nèi)的代碼執(zhí)行完畢后,該環(huán)境被銷毀,同時保存在其中的所有變量和函數(shù)定義也隨之被銷毀)。2-1定義期函數(shù)定義的時候,都會創(chuàng)建一個[[scope]]屈性,通這個對象對應(yīng)的是一個對象的列表,列表屮的對象僅能javascript內(nèi)部訪問,沒法通過語法訪問。(scope也就是作用域的意思。)我們定義一全
5、局函數(shù)A,那么A函數(shù)就創(chuàng)建了一個A的[[scope]]屬性。此時,[[scope]]里面只包含了全局對象[GlobalObject]o而如果,我們在A的內(nèi)部定義一個B函數(shù),那B函數(shù)同樣會創(chuàng)建一個[[scope]]屈性,B的[[scope]]屈性包含了兩個對彖,一個是A的活動對彖ActivationObjects一個是全局對彖,A的活動對彖在前面,全局對彖排在后面。簡而言之,一個函數(shù)的[Scope]屬性中對象列表的順序是上一層函數(shù)的ActivationObject對彖,然后是上上層的,一直到最外層的全局對彖。卜而是示例代碼:A只冇一個scop
6、e,B冇兩個scope//外部函數(shù)functionA(){varsomevar;//內(nèi)部函數(shù)functionB(){varsomevar;}2-2執(zhí)行期當函數(shù)被執(zhí)行的吋候,就是進入這個函數(shù)的執(zhí)行環(huán)境,首先會創(chuàng)一個它自己的活動對象[ActivationObject](這個對象中包含了this、參數(shù)(arguments)>局部變量(包括命名的參數(shù))的定義和一個變量對象的作用域鏈[[scopechain]],然后,把這個執(zhí)行環(huán)境的[scope]按順序復制到[[scopechain]]里,最后把這個活動對彖推入到[[scopechain]]的頂部。
7、這樣[[scopechain]]就是一個有序的棧,這樣保了對執(zhí)行環(huán)境有權(quán)訪問的所有變量和對象的有序訪問。//笫一步頁面載入創(chuàng)全局執(zhí)彳亍環(huán)境globalexecutingcontext和全局活動彖//定義全局[[scope]],只含有Window對象//掃描全局的定義變量及函數(shù)對象:color[undefined]>changecolor[FD創(chuàng)建changecolor的[[scope]],此時里面只含有全局活動對象】,加入到window中,所以全局變量和全局函數(shù)對象都是做為window的屈性定義的。//程序已經(jīng)定義好所以在此執(zhí)行環(huán)境內(nèi)任何位
8、置都可以執(zhí)行changecolor(),color也已經(jīng)被定義,但是它的值是undefined//第二步color賦值"blue"varcolor="blue";//它是不需要賦