最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript 作用域鏈解析

 更新時間:2014年11月13日 15:25:34   投稿:hebedich  
一直對Js的作用域有點迷糊,今天偶然讀到Javascript權(quán)威指南,立馬被吸引住了,寫的真不錯。我看的是第六版本,相當(dāng)?shù)暮?,大?000多頁,Js博大精深,要熟悉精通需要大毅力大功夫。謝謝心得吧

JavaScript中有Scope(作用域),Scope chain(作用域鏈),Execute context(執(zhí)行上下文),Active Object (活動對象),Dynamic Scope(動態(tài)作用域),Closure(閉包)這些概念,要理解這些概念,我們從靜態(tài)和動態(tài)兩個方面去分析一下。

首先我們寫一個簡單的function來做一個例子:

復(fù)制代碼 代碼如下:

function add(num1, num2){
var sum = num1 + num2;
return sum;
}

我們定義了一個具有兩個形參的add函數(shù)。

靜態(tài)方面:

當(dāng)創(chuàng)建add函數(shù)的時候,Javascript引擎會創(chuàng)建add函數(shù)的Scope chain,這個作用域鏈指向了Global Context(全局上下文)。如果用圖形形象化的表述如下圖所示:

從上圖可以看出,當(dāng)add函數(shù)創(chuàng)建的時候,作用域鏈就已經(jīng)創(chuàng)建了,因此可以得出一個結(jié)論,函數(shù)的作用域鏈?zhǔn)莿?chuàng)建函數(shù)的時候就已經(jīng)創(chuàng)建了,而不是動態(tài)運行期。下面就來看看動態(tài)運行期的時候會發(fā)生什么事情。

動態(tài)方面:

當(dāng)執(zhí)行add函數(shù)的時候,JavaScript會創(chuàng)建一個Execute context(執(zhí)行上下文),執(zhí)行上下文中就包含了add函數(shù)運行期所需要的所有信息。Execute context也有自己的Scope chain,當(dāng)函數(shù)運行的時候,JavaScript引擎會首先從用add函數(shù)的作用域鏈來初始化執(zhí)行上下文的作用域鏈,然后JavaScript引擎又會創(chuàng)建一個Active Object,這個對象里面包含了函數(shù)運行期的所有局部變量,參數(shù)以及this等變量。

如果形象的描述add函數(shù)動態(tài)運行期會發(fā)生什么,可以用如下圖來描述:

從上圖可以看出,執(zhí)行上下文是一個動態(tài)的概念,它是當(dāng)函數(shù)運行的時候創(chuàng)建的,同時Active Object對象也是一個動態(tài)的概念,它是被執(zhí)行上下文的作用域鏈引用的。因此可以得出一個結(jié)論:執(zhí)行上下文和活動對象都是動態(tài)概念,并且執(zhí)行上下文的作用域鏈?zhǔn)怯珊瘮?shù)作用域鏈初始化的。

上面說了函數(shù)作用域和執(zhí)行上下文作用域,下面接著說一下動態(tài)作用域的問題,當(dāng)在JavaScript通過with語句,try-catch的catch子句,以及eval方法的時候,JavaScript引擎就會動態(tài)的改變執(zhí)行上下文的作用域。下面還是通過一個例子來看看:

復(fù)制代碼 代碼如下:

function initUI(){ 
  with (document){ //avoid! 
  var bd = body, 
  links = getElementsByTagName("a"), 
  i= 0, 
  len = links.length; 
  while(i < len){ 
  update(links[i++]); 

  getElementById("go-btn").onclick = function(){ 
  start(); 
}; 
  bd.className = "active"; 


當(dāng)執(zhí)行上面的initUI函數(shù)的時候,JavaScript會動態(tài)的創(chuàng)建一個with語句對應(yīng)的作用域放到執(zhí)行上下文作用域鏈的最前端,通過下圖可以形象的描述上述過程,下圖紅色標(biāo)注的區(qū)域就顯示了with語句產(chǎn)生的作用域。

最后,我們來看看JavaScript最神秘的Closure(閉包),閉包在JavaScript其實就是一個函數(shù),閉包是在函數(shù)運行期被創(chuàng)建的,下面還是以一個實例來看看:

復(fù)制代碼 代碼如下:

function assignEvents(){ 
    var id = "xdi9592"; 
    document.getElementById("save-btn").onclick = function(event){ 
    saveDocument(id); 
   }; 


當(dāng)上面的assignEvents函數(shù)被執(zhí)行的時候,會創(chuàng)建一個閉包,而這個閉包會引用assignEvents作用域中的id變量,如果按照傳統(tǒng)的編程語言的方式,id是存儲在堆棧上的一個變量,當(dāng)函數(shù)執(zhí)行完了以后id就消失,那么怎么可能再次引用呢?顯然這里JavaScript采用了另外的方式。下面就來看看JavaScript是如何來實現(xiàn)閉包的。當(dāng)執(zhí)行assignEvents函數(shù)的時候,JavaScript引擎會創(chuàng)建assignEvents函數(shù)執(zhí)行上下文的作用域鏈,這個作用域鏈包含了assignEvents執(zhí)行時的活動對象,而同時JavaScript引擎也會創(chuàng)建一個閉包,而閉包的作用域鏈也會引用assignEvent執(zhí)行時候的活動對象,這樣當(dāng)assignEvents執(zhí)行完的時候,雖然它本身執(zhí)行上下文的作用域鏈不再引用活動對象了,但是閉包還是引用著assignEvents運行期對應(yīng)的活動對象,這就解釋了JavaScipt內(nèi)部的閉包機制??梢杂孟聢D形象的表述上面assignEvents函數(shù)運行期的情形:

從上面可以看出,當(dāng)assignEvents函數(shù)執(zhí)行完畢以后,document.getElementById("save-btn").onclick引用了閉包,這樣當(dāng)用戶點擊save-btn的時候,就會觸發(fā)閉包的執(zhí)行,那么下面就來看看閉包執(zhí)行時的情形。前面也說了JavaScript中閉包其實就是函數(shù),因此閉包執(zhí)行和函數(shù)執(zhí)行時的情形是一致的,通過下圖來形象的描述上述onclick事件所關(guān)聯(lián)的閉包。

從上圖可以看出JavaScript引擎首先創(chuàng)建了閉包的執(zhí)行上下文,然后用閉包作用域鏈來初始化閉包的執(zhí)行上下文作用域鏈,最后再將閉包執(zhí)行時對應(yīng)的活動對象放入到作用域的最前端,這也進一步驗證了閉包就是函數(shù)的論斷。

相關(guān)文章

最新評論

宿迁市| 绥棱县| 西乌珠穆沁旗| 稷山县| 开封县| 舟山市| 乐业县| 舟曲县| 安徽省| 海南省| 洞口县| 临泉县| 珲春市| 武定县| 仪陇县| 博罗县| 安溪县| 准格尔旗| 黑河市| 文昌市| 广丰县| 奉化市| 康平县| 清涧县| 沁阳市| 鲁甸县| 松溪县| 昆山市| 玉树县| 勐海县| 平顶山市| 沈阳市| 马龙县| 济南市| 尉犁县| 项城市| 疏附县| 平顶山市| 沛县| 巫溪县| 怀安县|