小編給大家分享一下JavaScript閉包與作用域鏈的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)是專業(yè)的安平網(wǎng)站建設(shè)公司,安平接單;提供網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行安平網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!閉包定義
閉包指的是有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常見方式,就是在一個(gè)函數(shù)A內(nèi)部創(chuàng)建另一個(gè)函數(shù)B,那么函數(shù)B就是一個(gè)閉包,可以訪問函數(shù)A作用域中的所有變量。
JavaScript的閉包與作用域鏈密不可分,因此本文可以和JavaScript的作用域鏈相對照分析,一定可以對JavaScript的閉包和作用域鏈有更深的理解。
下面我們?nèi)匀灰詂reateComparisonFunction為例進(jìn)行閉包的分析。
//step1: define createComparisonFunction function createComparisonFunction(propertyName){ return function(object1, object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } }; } //step2: call createComparisonFunction var compareName = createComparisonFunction("name"); var compareAge = createComparisonFunction("age"); //step3: call compare var object1 = { name : "Nicholas", age : 25 }; var object2 = { name : "Greg", age : 27 }; var result1 = compareName(object1, object2); // 1 var result2 = compareAge(object1, object2); // -1 //step4: dereference closure for recycle memory compareName = null; compareAge = null;
在這個(gè)例子中,匿名函數(shù)function(object1, object2)是一個(gè)閉包,能訪問createComparisonFunction作用域里的所有變量,自然也包含propertyName屬性, 因?yàn)閜ropertyName參數(shù)的不同,導(dǎo)致比較的屬性也有所不同,從而函數(shù)執(zhí)行結(jié)果也有不同。
閉包與變量
從JavaScript的作用域鏈中,我們了解到JavaScript是通過作用域鏈來確定函數(shù)執(zhí)行環(huán)境的作用域的,這種機(jī)制會(huì)引出一個(gè)值得注意的副作用,即閉包只能取得包含函數(shù)中任何變量的最后一個(gè)值。閉包是通過引用外部函數(shù)的活動(dòng)對象來訪問該活動(dòng)對象中的所有變量,因此在外部函數(shù)執(zhí)行過程中,這些變量的值可能會(huì)變化,但是在外部函數(shù)執(zhí)行完畢之后,外部函數(shù)的活動(dòng)對象便不會(huì)再改變,因此在執(zhí)行閉包的時(shí)候,閉包通過作用域鏈訪問到外部函數(shù)的活動(dòng)對象中的所有變量都只可能是在外部函數(shù)執(zhí)行完畢之后,外部函數(shù)的活動(dòng)對象中最后所保存的值。我們通過一個(gè)例子來說明這種副作用。
function createFunctions(){ var result = new Array(); for (var i = 0; i < 10; i++){ result[i] = function(){ return i; }; } return result; } var functions = createFunctions(); for(var i = 0; i < functions.length; i++){ console.log(functions[i]()); }
輸出的結(jié)果是
10 10 10 10 10 10 10 10 10 10
從表面上看,似乎每個(gè)函數(shù)都應(yīng)該返回自己的索引值,但實(shí)際上,每個(gè)函數(shù)都返回10。因?yàn)槊總€(gè)函數(shù)的作用域鏈中都保存著createFunctions函數(shù)的活動(dòng)對象,所以他們引用的都是這個(gè)createFunctions函數(shù)的活動(dòng)對象中的變量i,在createFunctions函數(shù)返回之后,變量i的值是10,此時(shí)每個(gè)函數(shù)都引用著保存變量i的同一個(gè)變量對象,所以每個(gè)函數(shù)內(nèi)部i的值都是10。
我們以調(diào)用functions[3]()
為例,圖解一下:
Closure函數(shù)的Function對象的作用域鏈引用的createFunctions的活動(dòng)對象中保留的變量i的值為10。所以不管是functions[3]()
還是functions[5]()
,其運(yùn)行時(shí)上下文的作用域鏈引用的createFunctions的活動(dòng)對象都是同一個(gè)活動(dòng)對象,該活動(dòng)對象中保留的變量i的值是10。
如何避免這種局面?我們可以通過創(chuàng)建另一個(gè)匿名函數(shù)讓閉包的行為符合預(yù)期。
function createFunctions(){ var result = new Array(); for (var i = 0; i < 10; i++){ result[i] = function(num){ return function(){ return num; } }(i); } return result; } var functions = createFunctions(); for(var i = 0; i < functions.length; i++){ console.log(functions[i]()); }
輸出的結(jié)果是
0 1 2 3 4 5 6 7 8 9
這個(gè)代碼片段與前面的代碼的區(qū)別在于立即調(diào)用了一個(gè)匿名函數(shù)function(num),使得閉包function()引用的是function(num)的活動(dòng)對象,訪問的是該活動(dòng)對象中的變量num而不是createFunctions活動(dòng)對象中的變量i,而在立即調(diào)用function(num)的num是索引值0,1,2…9。
我們?nèi)耘f以調(diào)用functions[3]()
為例,圖解一下:
在執(zhí)行createFunctions函數(shù)的時(shí)候,會(huì)依次調(diào)用function(0), function(1) … function(9), 生成function(0), function(1) … function(9)這10個(gè)function(num)的活動(dòng)對象,而result[0], result[1] … result[9]這10個(gè)匿名函數(shù)對象的作用域鏈分別引用這10個(gè)function(num)的活動(dòng)對象,而其中的變量num的值也對應(yīng)的為0, 1 … 9。
所以不管是functions[3]()
還是functions[5]()
,其運(yùn)行時(shí)上下文的作用域鏈都會(huì)引用在執(zhí)行createFunctions函數(shù)時(shí)候所執(zhí)行的function(3)或者function(5)這些function(num)函數(shù)的活動(dòng)對象,這些活動(dòng)對象都是不同的活動(dòng)對象,其中保留的num值分別為3, 5。
以上是“JavaScript閉包與作用域鏈的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
當(dāng)前名稱:JavaScript閉包與作用域鏈的示例分析-創(chuàng)新互聯(lián)
網(wǎng)站網(wǎng)址:http://muchs.cn/article24/dooeje.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、品牌網(wǎng)站設(shè)計(jì)、自適應(yīng)網(wǎng)站、微信小程序、網(wǎng)站改版、虛擬主機(jī)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容