茄子在线看片免费人成视频,午夜福利精品a在线观看,国产高清自产拍在线观看,久久综合久久狠狠综合

    <s id="ddbnn"></s>
  • <sub id="ddbnn"><ol id="ddbnn"></ol></sub>

  • <legend id="ddbnn"></legend><s id="ddbnn"></s>

    javascript執(zhí)行環(huán)境及作用域詳解
    來(lái)源:易賢網(wǎng) 閱讀:1219 次 日期:2016-07-06 09:23:53
    溫馨提示:易賢網(wǎng)小編為您整理了“javascript執(zhí)行環(huán)境及作用域詳解”,方便廣大網(wǎng)友查閱!

    這篇文章主要為大家詳細(xì)介紹了javascript執(zhí)行環(huán)境及作用域,分別針對(duì)javascript執(zhí)行環(huán)境及作用域進(jìn)行探討,感興趣的小伙伴們可以參考一下

    最近在重讀《javascript高級(jí)程序設(shè)計(jì)3》,覺得應(yīng)該寫一些博客記錄一下學(xué)習(xí)的一些知識(shí),不然都忘光啦。今天要總結(jié)的是js執(zhí)行環(huán)境和作用域。

    首先來(lái)說(shuō)一下執(zhí)行環(huán)境 

    一、執(zhí)行環(huán)境

    書上概念,執(zhí)行環(huán)境定義了變量或者函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了他們各自的行為。每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象。環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中。雖然我們?cè)诰帉懘a的時(shí)候無(wú)法訪問這個(gè)對(duì)象,但解析器在處理數(shù)據(jù)時(shí)會(huì)在后臺(tái)用到它。

    執(zhí)行環(huán)境是一個(gè)概念,一種機(jī)制,它定義了變量或函數(shù)是否有權(quán)訪問其他數(shù)據(jù)

    在javascript中,可執(zhí)行的JavaScript代碼分三種類型: 

    1. Global Code,即全局的、不在任何函數(shù)里面的代碼,例如:一個(gè)js文件、嵌入在HTML頁(yè)面中的js代碼等。 

    2. Eval Code,即使用eval()函數(shù)動(dòng)態(tài)執(zhí)行的JS代碼。 

    3. Function Code,即用戶自定義函數(shù)中的函數(shù)體JS代碼。

    跳過(guò)Eval Code,只說(shuō)全局執(zhí)行環(huán)境和函數(shù)執(zhí)行環(huán)境。 

    1、全局環(huán)境:

    全局環(huán)境是最外圍的一個(gè)執(zhí)行環(huán)境。全局執(zhí)行環(huán)境被認(rèn)為是window對(duì)象。因此所有全局變量和函數(shù)都是作為window對(duì)象的屬性和方法創(chuàng)建的。代碼載入瀏覽器時(shí),全局執(zhí)行環(huán)境被創(chuàng)建(當(dāng)我們關(guān)閉網(wǎng)頁(yè)或者瀏覽器時(shí)全局執(zhí)行環(huán)境才被銷毀)。比如在一個(gè)頁(yè)面中,第一次載入JS代碼時(shí)創(chuàng)建一個(gè)全局執(zhí)行環(huán)境。

    這也是為什么閉包有一個(gè)內(nèi)存泄露的缺點(diǎn)。因?yàn)殚]包中外部函數(shù)被當(dāng)成了全局環(huán)境。所以不會(huì)被銷毀,一直保存在內(nèi)存中。

    2、函數(shù)執(zhí)行環(huán)境

    每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境,當(dāng)執(zhí)行進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的執(zhí)行環(huán)境就會(huì)被推入一個(gè)執(zhí)行環(huán)境棧的頂部并獲取執(zhí)行權(quán)。當(dāng)這個(gè)函數(shù)執(zhí)行完畢,它的執(zhí)行環(huán)境又從這個(gè)棧的頂部被刪除,并把執(zhí)行權(quán)并還給之前執(zhí)行環(huán)境。這就是ECMAScript程序中的執(zhí)行流。

    也可以這樣解讀:當(dāng)調(diào)用一個(gè) JavaScript 函數(shù)時(shí),該函數(shù)就會(huì)進(jìn)入與該函數(shù)相對(duì)應(yīng)的執(zhí)行環(huán)境。如果又調(diào)用了另外一個(gè)函數(shù),則又會(huì)創(chuàng)建一個(gè)新的執(zhí)行環(huán)境,并且在函數(shù)調(diào)用期間執(zhí)行過(guò)程都處于該環(huán)境中。當(dāng)調(diào)用的函數(shù)返回后,執(zhí)行過(guò)程會(huì)返回原始執(zhí)行環(huán)境。因而,運(yùn)行中的 JavaScript 代碼就構(gòu)成了一個(gè)執(zhí)行環(huán)境棧。

    當(dāng)函數(shù)被調(diào)用時(shí)函數(shù)的局部環(huán)境被創(chuàng)建(函數(shù)內(nèi)的代碼執(zhí)行完畢后,該環(huán)境被銷毀,同時(shí)保存在其中的所有變量和函數(shù)定義也隨之被銷毀)。

    2-1定義期 

    函數(shù)定義的時(shí)候,都會(huì)創(chuàng)建一個(gè)[[scope]]屬性,通這個(gè)對(duì)象對(duì)應(yīng)的是一個(gè)對(duì)象的列表,列表中的對(duì)象僅能javascript內(nèi)部訪問,沒法通過(guò)語(yǔ)法訪問。

    (scope也就是作用域的意思。) 

    我們定義一全局函數(shù)A,那么A函數(shù)就創(chuàng)建了一個(gè)A的[[scope]]屬性。此時(shí),[[scope]]里面只包含了全局對(duì)象【Global Object】。

    而如果, 我們?cè)贏的內(nèi)部定義一個(gè)B函數(shù),那B函數(shù)同樣會(huì)創(chuàng)建一個(gè)[[scope]]屬性,B的[[scope]]屬性包含了兩個(gè)對(duì)象,一個(gè)是A的活動(dòng)對(duì)象Activation Object、一個(gè)是全局對(duì)象,A的活動(dòng)對(duì)象在前面,全局對(duì)象排在后面。

    簡(jiǎn)而言之,一個(gè)函數(shù)的[Scope]屬性中對(duì)象列表的順序是上一層函數(shù)的Activation Object對(duì)象,然后是上上層的,一直到最外層的全局對(duì)象。  

    下面是示例代碼:A只有一個(gè)scope,B有兩個(gè)scope

    // 外部函數(shù)

    function A(){

      var somevar;

      // 內(nèi)部函數(shù)

     function B(){

       var somevar;

      }

    }

    2-2執(zhí)行期 

    當(dāng)函數(shù)被執(zhí)行的時(shí)候,就是進(jìn)入這個(gè)函數(shù)的執(zhí)行環(huán)境,首先會(huì)創(chuàng)一個(gè)它自己的活動(dòng)對(duì)象【Activation Object】(這個(gè)對(duì)象中包含了this、參數(shù)(arguments)、局部變量(包括命名的參數(shù))的定義和一個(gè)變量對(duì)象的作用域鏈[[scope chain]],然后,把這個(gè)執(zhí)行環(huán)境的[scope]按順序復(fù)制到[[scope chain]]里,最后把這個(gè)活動(dòng)對(duì)象推入到[[scope chain]]的頂部。這樣[[scope chain]]就是一個(gè)有序的棧,這樣保了對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和對(duì)象的有序訪問。

    // 第一步頁(yè)面載入創(chuàng)全局執(zhí)行環(huán)境global executing context和全局活動(dòng)象

    // 定義全局[[scope]],只含有Window對(duì)象

    // 掃描全局的定義變量及函數(shù)對(duì)象:color【undefined】、changecolor【FD創(chuàng)建changecolor的[[scope]],此時(shí)里面只含有全局活動(dòng)對(duì)象】,加入到window中,所以全局變量和全局函數(shù)對(duì)象都是做為window的屬性定義的。

    // 程序已經(jīng)定義好所以在此執(zhí)行環(huán)境內(nèi)任何位置都可以執(zhí)行changecolor(),color也已經(jīng)被定義,但是它的值是undefined

    // 第二步color賦值"blue"

    var color = "blue";

    // 它是不需要賦值的,它就是引用本身

    function changecolor() {

     // 第四步進(jìn)入changecolor的執(zhí)行環(huán)境

     // 復(fù)制changecolor的[[scope]]到scope chain

     // 創(chuàng)建活動(dòng)對(duì)象,掃描定義變量和定義函數(shù),anothercolor【undefined】和swapcolors【FD創(chuàng)建swapcolors的[[scope]]加入changecolor的活動(dòng)對(duì)象和全局活動(dòng)對(duì)象】加入到活動(dòng)對(duì)象,活動(dòng)對(duì)象中同時(shí)還要加入arguments和this

     // 活動(dòng)對(duì)象推入scope chain 頂端

     // 程序已經(jīng)定義好所以在此執(zhí)行環(huán)境內(nèi)任何位置都可以執(zhí)行swapcolors(),anothercolor也已經(jīng)被定義好,但它的值是undefined

     // 第五anothercolor賦值"red"

     var anothercolor = "red";

     // 它是不需要賦值的,它就是引用本身

     function swapcolors() {

      // 第七步進(jìn)入swapcolors的執(zhí)行環(huán)境,創(chuàng)建它的活動(dòng)對(duì)象

      // 復(fù)制swapcolors的[[scope]]到scope chain

      // 掃描定義變量和定義函數(shù)對(duì)象,活動(dòng)對(duì)象中加入變量tempcolor【undefined】以及arguments和this

      // 活動(dòng)對(duì)象推入scope chain 頂端

      // 第八步tempcolor賦值anothercolor,anothercolor和color會(huì)沿著scope chain被查到,并繼續(xù)往下執(zhí)行

      var tempcolor = anothercolor;

       anothercolor = color;

       color = tempcolor; 

     }

     // 第六步執(zhí)行swapcolors,進(jìn)入其執(zhí)行環(huán)境

     swapcolors();

    }

    // 第三步執(zhí)行changecolor,進(jìn)入其執(zhí)行環(huán)境

    changecolor();

    2-3訪問標(biāo)識(shí)符:

    當(dāng)執(zhí)行js代碼的過(guò)程中,遇到一個(gè)標(biāo)識(shí)符,就會(huì)根據(jù)標(biāo)識(shí)符的名稱,在執(zhí)行上下文(Execution Context)的作用域鏈中進(jìn)行搜索。從作用域鏈的第一個(gè)對(duì)象(該函數(shù)的Activation Object對(duì)象)開始,如果沒有找到,就搜索作用域鏈中的下一個(gè)對(duì)象,如此往復(fù),直到找到了標(biāo)識(shí)符的定義。如果在搜索完作用域中的最后一個(gè)對(duì)象,也就是全局對(duì)象(Global Object)以后也沒有找到,則會(huì)拋出一個(gè)錯(cuò)誤,提示undefined。  

    二、Scope/Scope Chain(作用域/作用域鏈)

     當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),都會(huì)創(chuàng)建一個(gè)作用域鏈。 作用域鏈的用途是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。整個(gè)作用域鏈?zhǔn)怯刹煌瑘?zhí)行位置上的變量對(duì)象按照規(guī)則所構(gòu)建一個(gè)鏈表。作用域鏈的最前端,始終是當(dāng)前正在執(zhí)行的代碼所在環(huán)境的變量對(duì)象。

    如果這個(gè)環(huán)境是函數(shù),則將其活動(dòng)對(duì)象(activation object)作為變量對(duì)象?;顒?dòng)對(duì)象在最開始時(shí)只包含一個(gè)變量,就是函數(shù)內(nèi)部的arguments對(duì)象。作用域鏈中的下一個(gè)變量對(duì)象來(lái)自該函數(shù)的包含環(huán)境,而再下一個(gè)變量對(duì)象來(lái)自再下一個(gè)包含環(huán)境。這樣,一直延續(xù)到全局執(zhí)行環(huán)境,全局執(zhí)行環(huán)境的Variable Object始終是作用域鏈中的最后一個(gè)對(duì)象。

    如圖所示:

    名單

    書中例子:

    var color="blue";

     function changecolor(){

     var anothercolor="red";

     function swapcolors(){

     var tempcolor=anothercolor;

     anothercolor=color;

     color=tempcolor;

      // Todo something  

      }

     swapcolors();

    }

    changecolor();

     //這里不能訪問tempcolor和anocolor;但是可以訪問color;

    alert("Color is now "+color);

       通過(guò)上面的分析,我們可以得知內(nèi)部環(huán)境可以通過(guò)作用域鏈訪問所有的外部環(huán)境,但外部環(huán)境不能訪問內(nèi)部環(huán)境中的任何變量和函數(shù)。

    這些環(huán)境之間是線性、有次序的。每個(gè)環(huán)境都可以向上搜索作用域鏈,以便查詢變量和函數(shù)名;但任何環(huán)境不能通過(guò)向下搜索作用域鏈條而進(jìn)入另一個(gè)執(zhí)行環(huán)境。

    對(duì)于上述例子的swapcolor()函數(shù)而言,其作用域鏈包括:swapcolor()的變量對(duì)象、changecolor()變量對(duì)象和全局對(duì)象。swapcolor()的局部環(huán)境開始先在自己的Variable Object中搜索變量和函數(shù)名,找不到,則向上搜索changecolor作用域鏈。。。。。以此類推。但是,changecolor()函數(shù)是無(wú)法訪問swapcolor中的變量

     啟示:盡量使用局部變量,能夠減少搜索的時(shí)間 

    1、沒有塊級(jí)作用域

    與C、C++以及JAVA不同,Javscript沒有塊級(jí)作用域。看下面代碼:

    if(true){

      var myvar = "張三"; 

     }

     alert(myvar);// 張三

    如果有塊級(jí)作用域,外部是訪問不到myvar的。再看下面 

    for (var i=0;i<10;i++){

       console.log(i) 

      }

      alert(i); // 10

    對(duì)于有塊級(jí)作用域的語(yǔ)言來(lái)說(shuō),比如java或是c#代碼,i做為for初始化的變量,在for之外是訪問不到的。因?yàn)閕只存在于for循環(huán)體重,在運(yùn)行完for循環(huán)后,for中的所有變量就被銷毀了。而在javascript中則不是這樣的,在for中的變量聲明將會(huì)添加到當(dāng)前的執(zhí)行環(huán)境中(這里是全局執(zhí)行環(huán)境),因此在for循環(huán)完后,變量i依舊存在于循環(huán)外部的執(zhí)行環(huán)境。因此,會(huì)輸出10。

     2、聲明變量

       使用var聲明變量時(shí),這個(gè)變量將被自動(dòng)添加到距離最近的可用環(huán)境中。對(duì)于函數(shù)內(nèi)部,最接近的環(huán)境就是函數(shù)的局部變量。如果初始化變量時(shí)沒有使用var,該變量會(huì)自動(dòng)添加到全局函數(shù)中。

    代碼如下:

    var name = "小明";

    function getName(){

     alert( name ); //'undefined'

     var name = '小黃';

     alert(name ); //小黃

    }

    getName()

    為什么第一個(gè)name是undefined呢。這是因?yàn)椋琷avascript解析器,進(jìn)入一個(gè)函數(shù)執(zhí)行環(huán)境,先對(duì)var 和 function進(jìn)行掃描。

    相當(dāng)于會(huì)把var或者function【函數(shù)聲明】聲明提升到執(zhí)行環(huán)境頂部。

    也就是說(shuō),進(jìn)入我們的getName函數(shù)的時(shí)候,標(biāo)識(shí)符查找機(jī)制查找到了var,查找的name是局部變量name,而不是全局的name,因?yàn)楹瘮?shù)里面的name被提升到了頂部。

    上面的代碼會(huì)被解析成下面這樣:

    var name = "小明";

    function getName(){

     var name;

     alert( name ); //'undefined'

     var name = '小黃';

     alert(name ); //小黃

    }

    getName()

    延長(zhǎng)作用域鏈:

    雖然執(zhí)行環(huán)境只有兩種——全局作用域和函數(shù)作用域,但是還是可以通過(guò)某種方式來(lái)延長(zhǎng)作用域鏈。因?yàn)橛行┱Z(yǔ)句可以在作用域鏈的頂部增加一個(gè)臨時(shí)的變量對(duì)象。

    有兩種情況會(huì)發(fā)生這種現(xiàn)象:

    1、try-catch語(yǔ)句的catch塊;

    2、with語(yǔ)句;

    以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)理解javascript執(zhí)行環(huán)境及作用域有所幫助。

    更多信息請(qǐng)查看網(wǎng)絡(luò)編程
    易賢網(wǎng)手機(jī)網(wǎng)站地址:javascript執(zhí)行環(huán)境及作用域詳解
    由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

    2026上岸·考公考編培訓(xùn)報(bào)班

    • 報(bào)班類型
    • 姓名
    • 手機(jī)號(hào)
    • 驗(yàn)證碼
    關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
    工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
    云南網(wǎng)警備案專用圖標(biāo)
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
    云南網(wǎng)警報(bào)警專用圖標(biāo)