欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 作用域鏈解析

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

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

首先我們寫(xiě)一個(gè)簡(jiǎn)單的function來(lái)做一個(gè)例子:

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

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

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

靜態(tài)方面:

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

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

動(dòng)態(tài)方面:

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

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

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

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

復(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ù)的時(shí)候,JavaScript會(huì)動(dòng)態(tài)的創(chuàng)建一個(gè)with語(yǔ)句對(duì)應(yīng)的作用域放到執(zhí)行上下文作用域鏈的最前端,通過(guò)下圖可以形象的描述上述過(guò)程,下圖紅色標(biāo)注的區(qū)域就顯示了with語(yǔ)句產(chǎn)生的作用域。

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

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

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


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

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

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

相關(guān)文章

  • Echarts圖例組件的屬性與源代碼

    Echarts圖例組件的屬性與源代碼

    圖例組件展現(xiàn)了不同系列的標(biāo)記(symbol),顏色和名字,可以通過(guò)點(diǎn)擊圖例控制哪些系列不顯示,這篇文章主要給大家介紹了關(guān)于Echarts圖例組件的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • JavaScript的事件機(jī)制詳解

    JavaScript的事件機(jī)制詳解

    事件是將JavaScript腳本與網(wǎng)頁(yè)聯(lián)系在一起的主要方式,是JavaScript中最重要的主題之一。本文將詳細(xì)探討JavaScript的事件機(jī)制,并對(duì)比分析了瀏覽器之間的不同,具體內(nèi)容包括事件流、事件處理程序綁定方式、事件對(duì)象等。
    2017-01-01
  • js實(shí)現(xiàn)選中頁(yè)面文字將其分享到新浪微博

    js實(shí)現(xiàn)選中頁(yè)面文字將其分享到新浪微博

    這篇文章主要介紹了js實(shí)現(xiàn)選中頁(yè)面文字將其分享到新浪微博,需要的朋友可以參考下
    2015-11-11
  • 潛說(shuō)js對(duì)象和數(shù)組

    潛說(shuō)js對(duì)象和數(shù)組

    潛說(shuō)js對(duì)象和數(shù)組 對(duì)象是一個(gè)無(wú)序?qū)傩约? 每個(gè)屬性都有自己的名字和值
    2011-05-05
  • js中async函數(shù)結(jié)合promise的小案例淺析

    js中async函數(shù)結(jié)合promise的小案例淺析

    這篇文章主要介紹了js中async函數(shù)結(jié)合promise的小案例淺析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • TypeScript中的類(lèi)型斷言和非空斷言的使用方法

    TypeScript中的類(lèi)型斷言和非空斷言的使用方法

    類(lèi)型斷言是一種方式,可以手動(dòng)指定變量的類(lèi)型,非空斷言是一種類(lèi)型斷言的特殊形式,這篇文章主要給大家介紹TypeScript 中的類(lèi)型斷言和非空斷言的使用方法,需要的朋友可以參考下
    2023-07-07
  • 深入理解選擇框腳本[推薦]

    深入理解選擇框腳本[推薦]

    選擇框是通過(guò)<select>和<option>元素創(chuàng)建的,又稱為下拉列表框。為了方便與這個(gè)控件交互,除了所有表單字段共有的屬性和方法外,javascript還提供了一些屬性和方法。本文將詳細(xì)介紹選擇框腳本
    2016-12-12
  • Javascript將string類(lèi)型轉(zhuǎn)換int類(lèi)型

    Javascript將string類(lèi)型轉(zhuǎn)換int類(lèi)型

    今天網(wǎng)站有個(gè)小功能要判斷用戶購(gòu)買(mǎi)商品數(shù)量是否大于庫(kù)存數(shù)據(jù),如果大于庫(kù)存數(shù)量,就給予提示。
    2010-12-12
  • 微信小程序?qū)崿F(xiàn)水平時(shí)間軸

    微信小程序?qū)崿F(xiàn)水平時(shí)間軸

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)水平時(shí)間軸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 淺談JavaScript對(duì)象的創(chuàng)建方式

    淺談JavaScript對(duì)象的創(chuàng)建方式

    下面小編就為大家?guī)?lái)一篇淺談JavaScript對(duì)象的創(chuàng)建方式。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06

最新評(píng)論