執(zhí)行環(huán)境,作用域理解_第1頁
執(zhí)行環(huán)境,作用域理解_第2頁
執(zhí)行環(huán)境,作用域理解_第3頁
執(zhí)行環(huán)境,作用域理解_第4頁
執(zhí)行環(huán)境,作用域理解_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Javascript學(xué)習(xí)---2、執(zhí)行環(huán)境,作用域作者:名劉天下來源:博客園發(fā)布時間:2010-12-1017:03閱讀:155次原文鏈接[收藏]在javascript的學(xué)習(xí)中,執(zhí)行環(huán)境、作用域是2個非常非常重要和基本的概念,理解了這2個概念對于javsacript中很多腳本的運行結(jié)果就能明白其中的道理了,比如搞清作用域和執(zhí)行環(huán)境對于閉包的理解至關(guān)重要。一、執(zhí)行環(huán)境(exectioncontext,也有稱之為執(zhí)行上下文)所有JavaScript代碼都是在一個執(zhí)行環(huán)境中被執(zhí)行的。執(zhí)行環(huán)境是一個概念,一種機制,用來完成JavaScript運行時在作用域、生存期等方面的處理,它定義了變量或函數(shù)是否有權(quán)訪問其他數(shù)據(jù),決定各自行為。在javascript中,可執(zhí)行的JavaScript代碼分三種類型:1.GlobalCode即全局的、不在任何函數(shù)里面的代碼,例如:一個js文件、嵌入在HTML頁面中的js代碼等。EvalCode,即使用eval()函數(shù)動態(tài)執(zhí)行的JS代碼。FunctionCode,即用戶自定義函數(shù)中的函數(shù)體JS代碼。不同類型的JavaScript代碼具有不同的執(zhí)行環(huán)境,這里我們不考慮evelcode,對應(yīng)于globalcode和functioncode存在2種執(zhí)行環(huán)境:全局執(zhí)行環(huán)境和函數(shù)執(zhí)行環(huán)境。在一個頁面中,第一次載入JS代碼時創(chuàng)建一個全局執(zhí)行環(huán)境,全局執(zhí)行環(huán)境是最外圍的執(zhí)行環(huán)境,在Web瀏覽器中,全局執(zhí)行環(huán)境被認為是window對象。因此,所有的全局變量和函數(shù)都是作為window對象的屬性和方法創(chuàng)建的。當調(diào)用一個JavaScript函數(shù)時,該函數(shù)就會進入與該函數(shù)相對應(yīng)的執(zhí)行環(huán)境。如果又調(diào)用了另外一個函數(shù)(或者遞歸地調(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)境棧。Code1:functionFn1(){functionFn2(){alert(document.body.tagName);//BODY//othercode...}Fn2();}Fn1();//codehere(圖1執(zhí)行環(huán)境棧摘自:笨蛋的座右銘的博文)程序在進入每個執(zhí)行環(huán)境的時候,JavaScript引擎在內(nèi)部創(chuàng)建一個對象,叫做變量對象(VariableObject)。對應(yīng)函數(shù)的每一個參數(shù),在VariableObject上添加一個屬性,屬性的名字、值與參數(shù)的名字、值相同。函數(shù)中每聲明一個變量,也會在VariableObject上添加一個屬性,名字就是變量名,因此為變量賦值就是給VariableObject對應(yīng)的屬性賦值。在函數(shù)中訪問參數(shù)或者局部變量時,就是在variableObject上搜索相應(yīng)的屬性,返回其值。(另外注意:一般情況下VariableObject是一個內(nèi)部對象,JS代碼中無法直接訪問。規(guī)范中對其實現(xiàn)方式也不做要求,因此它可能只是引擎內(nèi)部的一種數(shù)據(jù)結(jié)構(gòu)。)大致處理方式就這樣,但作用域的概念不只這么簡單,例如函數(shù)體中可以使用全局變量、函數(shù)嵌套定義時情況更復(fù)雜點。這些情況下怎樣處理?JavaScript引擎將不同執(zhí)行位置上的VariableObject按照規(guī)則構(gòu)建一個鏈表,在訪問一個變量時,先在鏈表的第1個VariableObject上查找,如果沒有找到則繼續(xù)在第2個VariableObject上查找,直到搜索結(jié)束。這就是Scope/ScopeChain的大致概念。二、Scope/ScopeChain(作用域/作用域鏈)當代碼在一個環(huán)境中執(zhí)行時,都會創(chuàng)建基于VariableObject的一個作用域鏈。作用域鏈的用途是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。整個作用域鏈是由不同執(zhí)行位置上的VariableObject按照規(guī)則所構(gòu)建一個鏈表。作用域鏈的最前端,始終是當前正在執(zhí)行的代碼所在環(huán)境的VariableObject。如果這個環(huán)境是函數(shù)(比如Fn2),則將其活動對象(activationobject)作為變量對象?;顒訉ο笤谧铋_始時只包含一個變量,就是函數(shù)內(nèi)部的arguments對象。作用域鏈中的下一個VariableObject來自該函數(shù)(Fn2)的包含環(huán)境(也就是Fn1),而再下一個Variableobject來自再下一個包含環(huán)境。這樣,一直延續(xù)到全局執(zhí)行環(huán)境,全局執(zhí)行環(huán)境的VariableObject始終是作用域鏈中的最后一個對象。如上所述,作用域鏈感覺就是一個VariableObject鏈表,當訪問一個變量時,先在鏈表的第一個VariableObject(最前端)上查找,如果沒有找到則繼續(xù)在第二個VariableObject上查找,直到搜索結(jié)束,也就是搜索到全局執(zhí)行環(huán)境的VariableObject中。這也就形成了ScopeChain的概念。與上面Code1代碼對應(yīng)的作用域鏈圖如下所示(摘自:笨蛋的座右銘的博文,這個圖感覺不是很理想,不如下面的圖3更形象,把右側(cè)這部分調(diào)個個就好了。)(圖2作用域鏈圖)如上圖所示,對于Codel代碼中的函數(shù)Fn2所對應(yīng)的作用域鏈為:Fn2VariableObject->Fn1variableObject->全局對象。也就是說,在Fn2函數(shù)中進行變量訪問時,首先會在Fn2Variableobject訪問內(nèi)進行尋找,如果沒有找到,則向上,搜索Fn1VariableObject中是否存在,直至找到,停止搜索。再拿《javascript高級程序設(shè)計第二版》中提到的例子來說明一下。代碼如下所示:Code2:varcolor="blue";functionchangecolor(){varanothercolor="red";functionswapcolors(){vartempcolor=anothercolor;anothercolor=color;color=tempcolor;//Todosomething}swapcolors();}changecolor();〃這里不能訪問tempcolor和anocolor;但是可以訪問color;alert("Colorisnow"+color);在Code2代碼中,涉及3個執(zhí)行環(huán)境全局環(huán)境、changecolor函數(shù)的局部環(huán)境和swapcolor局部環(huán)境。該段代碼的作用域鏈如下圖所示。

window《javascript高級程序設(shè)計第二版》)colorwindow《javascript高級程序設(shè)計第二版》)colorchar)geColor()——mmth略rSlQr——色wwpCcdqr串()I—tempCalcr(圖3摘自:上圖中,.-》全局環(huán)境有1個變量color和1個函數(shù)changecolor()。?-》changecolor()函數(shù)的局部環(huán)境中具有1個anothercolor屬性和1個swapcolors函數(shù),當然,changecolor函數(shù)中可以訪問自身以及它外圍(也就是全局環(huán)境)中的變量。?-》swapcolor()函數(shù)的局部環(huán)境中具有1個變量tempcolor。在該函數(shù)內(nèi)部可以訪問上面的2個環(huán)境(changecolor和window)中的所有變量,因為那2個環(huán)境都是它的父執(zhí)行環(huán)境。通過上面的分析,我們可以得知內(nèi)部環(huán)境可以通過作用域鏈訪問所有的外部環(huán)境,但外部環(huán)境不能訪問內(nèi)部環(huán)境中的任何變量和函數(shù)。這些環(huán)境之間是線性、有次序的。每個環(huán)境都可以向上搜索作用域鏈,以便查詢變量和函數(shù)名;但任何環(huán)境不能通過向下搜索作用域鏈條而進入另一個執(zhí)行環(huán)境。對于上述例子的swapcolor()函數(shù)而言,其作用域鏈包括:swapcolor()的變量對象、changecolor()變量對象和全局對象。swapcolor()的局部環(huán)境開始先在自己的VariableObject中搜索變量和函數(shù)名,找不到,則向上搜索changecolor作用域鏈。。。。。以此類推。但是,changecolor()函數(shù)是無法訪問swapcolor中的變量。關(guān)于作用域總結(jié)以下幾條:1、javascript沒有塊級作用域。直接上代碼:for(vari=0;i<10;i++){doSomething(i);}alert(i);//output:10,why?上述代碼運行后會返回10,為什么呢?如果是同樣的java或是c#代碼,則不會是10,可能會提示運行錯誤,因為i只存在于for循環(huán)體重,在運行完for循環(huán)后,for中的所有變量就被銷毀了。而在javascript中則不是這樣的,在for中的變量聲明將會添加到當前的執(zhí)行環(huán)境中(這里是全局執(zhí)行環(huán)境),因此在for循環(huán)完后,變量i依舊存在于循環(huán)外部的執(zhí)行環(huán)境。因此,會輸出10。2、聲明變量使用var聲明變量時,這個變量將被自動添加到距離最近的可用環(huán)境中。對于函數(shù)而言,自然聲明的變量就會被添加到函數(shù)的局部環(huán)境中,變量在整個函數(shù)環(huán)境內(nèi)都是可用的。但是,如果變量沒有是用var進行聲明,將會被添加到全局環(huán)境,也就是說成位全局變量了。所以在函數(shù)體內(nèi),進行聲明時,一般要在開頭用var進行聲明。最后出幾個小例題:varx=1;functionrain(){alert(x); 〃彈出'undefined',而不是1,也不是10,why?varx='10';alert(x); 〃彈出'10',why?}rain()為什么會是代碼中所說明的結(jié)果呢?我認為和2個事情有關(guān):作用域和預(yù)解析。我們可以很容易得出上述代碼的作用域鏈。window全局環(huán)境和rain()函數(shù)局部環(huán)境。window全局環(huán)境中存在全局變量x和ra

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論