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

深入理解Javascript閉包 新手版

 更新時(shí)間:2010年12月28日 19:53:03   作者:  
最近在網(wǎng)上查閱了不少Javascript閉包(closure)相關(guān)的資料,寫(xiě)的大多是非常的學(xué)術(shù)和專業(yè)。對(duì)于初學(xué)者來(lái)說(shuō)別說(shuō)理解閉包了,就連文字?jǐn)⑹龆己茈y看懂。撰寫(xiě)此文的目的就是用最通俗的文字揭開(kāi)Javascript閉包的真實(shí)面目。
 一、什么是閉包?

  “官方”的解釋是:所謂“閉包”,指的是一個(gè)擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個(gè)函數(shù)),因而這些變量也是該表達(dá)式的一部分。

  相信很少有人能直接看懂這句話,因?yàn)樗枋龅奶珜W(xué)術(shù)。我想用如何在Javascript中創(chuàng)建一個(gè)閉包來(lái)告訴你什么是閉包,因?yàn)樘^(guò)閉包的創(chuàng)建過(guò)程直接理解閉包的定義是非常困難的。看下面這段代碼:
復(fù)制代碼 代碼如下:

function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();

  這段代碼有兩個(gè)特點(diǎn):

  1、函數(shù)b嵌套在函數(shù)a內(nèi)部;

  2、函數(shù)a返回函數(shù)b。

  這樣在執(zhí)行完var c=a()后,變量c實(shí)際上是指向了函數(shù)b,再執(zhí)行c()后就會(huì)彈出一個(gè)窗口顯示i的值(第一次為1)。這段代碼其實(shí)就創(chuàng)建了一個(gè)閉包,為什么?因?yàn)楹瘮?shù)a外的變量c引用了函數(shù)a內(nèi)的函數(shù)b,就是說(shuō):

  當(dāng)函數(shù)a的內(nèi)部函數(shù)b被函數(shù)a外的一個(gè)變量引用的時(shí)候,就創(chuàng)建了一個(gè)閉包。

  我猜想你一定還是不理解閉包,因?yàn)槟悴恢篱]包有什么作用,下面讓我們繼續(xù)探索。

  二、閉包有什么作用?

  簡(jiǎn)而言之,閉包的作用就是在a執(zhí)行完并返回后,閉包使得Javascript的垃圾回收機(jī)制GC不會(huì)收回a所占用的資源,因?yàn)閍的內(nèi)部函數(shù)b的執(zhí)行需要依賴a中的變量。這是對(duì)閉包作用的非常直白的描述,不專業(yè)也不嚴(yán)謹(jǐn),但大概意思就是這樣,理解閉包需要循序漸進(jìn)的過(guò)程。

在上面的例子中,由于閉包的存在使得函數(shù)a返回后,a中的i始終存在,這樣每次執(zhí)行c(),i都是自加1后alert出i的值。

  那 么我們來(lái)想象另一種情況,如果a返回的不是函數(shù)b,情況就完全不同了。因?yàn)閍執(zhí)行完后,b沒(méi)有被返回給a的外界,只是被a所引用,而此時(shí)a也只會(huì)被b引 用,因此函數(shù)a和b互相引用但又不被外界打擾(被外界引用),函數(shù)a和b就會(huì)被GC回收。(關(guān)于Javascript的垃圾回收機(jī)制將在后面詳細(xì)介紹)

  三、閉包內(nèi)的微觀世界

  如 果要更加深入的了解閉包以及函數(shù)a和嵌套函數(shù)b的關(guān)系,我們需要引入另外幾個(gè)概念:函數(shù)的執(zhí)行環(huán)境(excution context)、活動(dòng)對(duì)象(call object)、作用域(scope)、作用域鏈(scope chain)。以函數(shù)a從定義到執(zhí)行的過(guò)程為例闡述這幾個(gè)概念。

  1、當(dāng)定義函數(shù)a的時(shí)候,js解釋器會(huì)將函數(shù)a的作用域鏈(scope chain)設(shè)置為定義a時(shí)a所在的“環(huán)境”,如果a是一個(gè)全局函數(shù),則scope chain中只有window對(duì)象。

  2、當(dāng)函數(shù)a執(zhí)行的時(shí)候,a會(huì)進(jìn)入相應(yīng)的執(zhí)行環(huán)境(excution context)。

  3、在創(chuàng)建執(zhí)行環(huán)境的過(guò)程中,首先會(huì)為a添加一個(gè)scope屬性,即a的作用域,其值就為第1步中的scope chain。即a.scope=a的作用域鏈。

  4、然后執(zhí)行環(huán)境會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象(call object)?;顒?dòng)對(duì)象也是一個(gè)擁有屬性的對(duì)象,但它不具有原型而且不能通過(guò)JavaScript代碼直接訪問(wèn)。創(chuàng)建完活動(dòng)對(duì)象后,把活動(dòng)對(duì)象添加到a的作用域鏈的最頂端。此時(shí)a的作用域鏈包含了兩個(gè)對(duì)象:a的活動(dòng)對(duì)象和window對(duì)象。

  5、下一步是在活動(dòng)對(duì)象上添加一個(gè)arguments屬性,它保存著調(diào)用函數(shù)a時(shí)所傳遞的參數(shù)。

  6、最后把所有函數(shù)a的形參和內(nèi)部的函數(shù)b的引用也添加到a的活動(dòng)對(duì)象上。在這一步中,完成了函數(shù)b的的定義,因此如同第3步,函數(shù)b的作用域鏈被設(shè)置為b所被定義的環(huán)境,即a的作用域。

  到此,整個(gè)函數(shù)a從定義到執(zhí)行的步驟就完成了。此時(shí)a返回函數(shù)b的引用給c,又函數(shù)b的作用域鏈包含了對(duì)函數(shù)a的活動(dòng)對(duì)象的引用,也就是說(shuō)b可以訪問(wèn)到a中定義的所有變量和函數(shù)。函數(shù)b被c引用,函數(shù)b又依賴函數(shù)a,因此函數(shù)a在返回后不會(huì)被GC回收。

  當(dāng)函數(shù)b執(zhí)行的時(shí)候亦會(huì)像以上步驟一樣。因此,執(zhí)行時(shí)b的作用域鏈包含了3個(gè)對(duì)象:b的活動(dòng)對(duì)象、a的活動(dòng)對(duì)象和window對(duì)象,如下圖所示:

  如圖所示,當(dāng)在函數(shù)b中訪問(wèn)一個(gè)變量的時(shí)候,搜索順序是先搜索自身的活動(dòng)對(duì)象,如果存在則返回,如果不存在將繼續(xù)搜索函數(shù)a的活動(dòng)對(duì)象,依 次查找,直到找到為止。如果整個(gè)作用域鏈上都無(wú)法找到,則返回undefined。如果函數(shù)b存在prototype原型對(duì)象,則在查找完自身的活動(dòng)對(duì)象 后先查找自身的原型對(duì)象,再繼續(xù)查找。這就是Javascript中的變量查找機(jī)制。

  四、閉包的應(yīng)用場(chǎng)景

  1、保護(hù)函數(shù)內(nèi)的變量安全。以最開(kāi)始的例子為例,函數(shù)a中i只有函數(shù)b才能訪問(wèn),而無(wú)法通過(guò)其他途徑訪問(wèn)到,因此保護(hù)了i的安全性。

  2、在內(nèi)存中維持一個(gè)變量。依然如前例,由于閉包,函數(shù)a中i的一直存在于內(nèi)存中,因此每次執(zhí)行c(),都會(huì)給i自加1。

  以上兩點(diǎn)是閉包最基本的應(yīng)用場(chǎng)景,很多經(jīng)典案例都源于此。

  五、Javascript的垃圾回收機(jī)制

  在Javascript中,如果一個(gè)對(duì)象不再被引用,那么這個(gè)對(duì)象就會(huì)被GC回收。如果兩個(gè)對(duì)象互相引用,而不再被第3者所引用,那么這兩個(gè)互相引用的對(duì)象也會(huì)被回收。因?yàn)楹瘮?shù)a被b引用,b又被a外的c引用,這就是為什么函數(shù)a執(zhí)行后不會(huì)被回收的原因。

相關(guān)文章

  • js方塊躲避游戲代碼

    js方塊躲避游戲代碼

    鼠標(biāo)控制,空色方塊不要讓藍(lán)色方塊碰到就可以,看能玩多久,是個(gè)javascript不錯(cuò)的一個(gè)游戲啊,想用js寫(xiě)游戲的朋友可以參考下,看代碼應(yīng)該是國(guó)外的人寫(xiě)的
    2008-05-05
  • 微信小程序input、textarea層級(jí)過(guò)高穿透的問(wèn)題解決

    微信小程序input、textarea層級(jí)過(guò)高穿透的問(wèn)題解決

    微信小程序原生組件camera、canvas、input、live-player、live、pusher、map、textarea、video的層級(jí)是最高的,那么如何解決微信小程序input、textarea層級(jí)過(guò)高穿透,本文就詳細(xì)的介紹一下
    2021-11-11
  • JavaScript定時(shí)器使用方法詳解

    JavaScript定時(shí)器使用方法詳解

    這篇文章主要介紹了JavaScript定時(shí)器的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • js中的cookie的讀寫(xiě)操作示例詳解

    js中的cookie的讀寫(xiě)操作示例詳解

    cookie是有有效期的,cookie的默認(rèn)有效期是從cookie生成至瀏覽器關(guān)閉,也可以通過(guò)設(shè)置cookie的有效期來(lái)指定其失效日期;用戶也可以禁止cookie也可以手動(dòng)刪除cookie
    2014-04-04
  • 微信小程序排坑指南詳解

    微信小程序排坑指南詳解

    這篇文章主要為大家詳細(xì)介紹了微信小程序排坑指南,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 微信小程序云開(kāi)發(fā)實(shí)現(xiàn)搜索功能

    微信小程序云開(kāi)發(fā)實(shí)現(xiàn)搜索功能

    這篇文章主要為大家詳細(xì)介紹了微信小程序云開(kāi)發(fā)實(shí)現(xiàn)搜索功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • javascript異步編程

    javascript異步編程

    如果編程加入了時(shí)間的概念就一切變得非常復(fù)雜。通常我們的程序是飛快地解析執(zhí)行,一毫秒緊接著一毫秒,從上至下地執(zhí)行,這稱之為同步。但如果我們想讓后臺(tái)的程序不等前面的程序執(zhí)行,就執(zhí)行呢,于是就有了異步的概念。
    2010-06-06
  • js模仿java的Map集合詳解

    js模仿java的Map集合詳解

    這篇文章主要介紹了js模仿java的Map集合的相關(guān)資料,Java中某些最常用的集合類(lèi)是List和Map,感興趣的小伙伴們可以了解一下
    2016-01-01
  • js設(shè)計(jì)模式之單例模式原理與用法詳解

    js設(shè)計(jì)模式之單例模式原理與用法詳解

    這篇文章主要介紹了js設(shè)計(jì)模式之單例模式原理與用法,結(jié)合實(shí)例形式詳細(xì)分析了javascript單例模式的概念、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2019-08-08
  • layui checkbox默認(rèn)選中,獲取選中值,清空所有選中項(xiàng)的例子

    layui checkbox默認(rèn)選中,獲取選中值,清空所有選中項(xiàng)的例子

    今天小編就為大家分享一篇layui checkbox默認(rèn)選中,獲取選中值,清空所有選中項(xiàng)的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-09-09

最新評(píng)論