摘要:閉包是怎么通過(guò)作用域鏈霸占更多內(nèi)存的本文是作者學(xué)習(xí)高級(jí)程序設(shè)計(jì)第一小節(jié)的一點(diǎn)個(gè)人理解,詳細(xì)教程請(qǐng)參考原教材。函數(shù)執(zhí)行過(guò)程創(chuàng)建了一個(gè)函數(shù)的活動(dòng)對(duì)象,作用域鏈的最前端指向這個(gè)對(duì)象。函數(shù)執(zhí)行完畢返回值后執(zhí)行環(huán)境作用域鏈和活動(dòng)對(duì)象一并銷(xiāo)毀。
JavaScript 閉包是怎么通過(guò)作用域鏈霸占更多內(nèi)存的?
本文是作者學(xué)習(xí)《JavaScript 高級(jí)程序設(shè)計(jì)》7.2第一小節(jié)的一點(diǎn)個(gè)人理解,詳細(xì)教程請(qǐng)參考原教材。
在弄清楚這個(gè)問(wèn)題之前,我們有必要搞清楚下面這幾個(gè)問(wèn)題:
首先,什么是閉包?怎么創(chuàng)建閉包?定義:閉包 是指 有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中變量的函數(shù)。
一個(gè)一般的函數(shù)執(zhí)行的時(shí)候都發(fā)生了什么?在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù),是創(chuàng)建閉包最常見(jiàn)的方式。
創(chuàng)建一個(gè)執(zhí)行環(huán)境,里面有這個(gè)函數(shù)的變量對(duì)象,保存了函數(shù)可訪問(wèn)的所有數(shù)據(jù)。
創(chuàng)建了作用域鏈,用來(lái)保證可訪問(wèn)變量的有序訪問(wèn)。
函數(shù)執(zhí)行過(guò)程創(chuàng)建了一個(gè)函數(shù)的活動(dòng)對(duì)象,作用域鏈的最前端指向這個(gè)對(duì)象。
函數(shù)讀取寫(xiě)入值,在作用域鏈里面查找。
函數(shù)執(zhí)行完畢返回值后:執(zhí)行環(huán)境、作用域鏈和活動(dòng)對(duì)象一并銷(xiāo)毀。
理解了這些之后,考察下原書(shū)的代碼:
function createCompare(property){ return function(obj1,obj2){ var value1=obj1.property; var value2=obj2.property; if (value2 < value1){ return 1; } else if (value2 >value1){ return 1; } else { return 0; } }; } var compareNames = createCompare("name"); var result = compareNames({name : "mars1"},{name : "mars2"});
其中,createCompare 函數(shù)返回了一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)就是一個(gè)閉包。它引用了createCompare函數(shù)的參數(shù)變量property。
創(chuàng)建compareNames 變量的時(shí)候,就創(chuàng)建了createCompare函數(shù)的活動(dòng)變量:其中property = name etc. 同時(shí)返回了匿名函數(shù)給compareNames變量,它也有自己的執(zhí)行環(huán)境與作用域鏈,作用域鏈引用了創(chuàng)建的compareNames活動(dòng)對(duì)象。
result 定義過(guò)程,創(chuàng)建了compareNames的活動(dòng)對(duì)象,其中obj1 = {name : "mars1"} etc.
這樣,為result 賦值的compareNames函數(shù)執(zhí)行環(huán)境的作用域鏈如下:
那么問(wèn)題來(lái)了,這個(gè)閉包是怎么導(dǎo)致占用更多內(nèi)存的?compareNames活動(dòng)對(duì)象 → createCompare活動(dòng)對(duì)象 → 全局對(duì)象。
函數(shù)執(zhí)行完畢,compareNames 變量并未消失,不會(huì)被垃圾回收,而它指向的閉包(匿名函數(shù))的作用域鏈引用著createCompare 函數(shù)的活動(dòng)變量。所以createCompare函數(shù)雖然執(zhí)行完畢返回了匿名函數(shù),但是它的活動(dòng)對(duì)象并不會(huì)和執(zhí)行環(huán)境、作用域鏈一樣被銷(xiāo)毀,因?yàn)檫€有compareNames的作用域鏈在引用。這樣就相當(dāng)于閉包攜帶了包含它的函數(shù)活動(dòng)對(duì)象。
因此要釋放compareNames攜帶的作用域,必須手動(dòng)解除引用:
var compareNames = null;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81593.html
摘要:但是,必須強(qiáng)調(diào),閉包是一個(gè)運(yùn)行期概念。通過(guò)原型鏈可以實(shí)現(xiàn)繼承,而與閉包相關(guān)的就是作用域鏈。常理來(lái)說(shuō),一個(gè)函數(shù)執(zhí)行完畢,其執(zhí)行環(huán)境的作用域鏈會(huì)被銷(xiāo)毀。所以此時(shí),的作用域鏈雖然銷(xiāo)毀了,但是其活動(dòng)對(duì)象仍在內(nèi)存中。 學(xué)習(xí)Javascript閉包(Closure)javascript的閉包JavaScript 閉包深入理解(closure)理解 Javascript 的閉包JavaScript ...
摘要:語(yǔ)句中的塊語(yǔ)句對(duì)來(lái)說(shuō),將會(huì)指定對(duì)象添加到作用域鏈中。在嚴(yán)格模式下,初始化未經(jīng)聲明的變量會(huì)導(dǎo)致錯(cuò)誤。查詢標(biāo)識(shí)符搜索過(guò)程從作用域鏈的前端開(kāi)始,向上逐級(jí)查詢與給定名字匹配的標(biāo)識(shí)符。 本文記錄了我在學(xué)習(xí)前端上的筆記,方便以后的復(fù)習(xí)和鞏固。 4.1基本類(lèi)型和引用類(lèi)型的值 ECMAScript變量可能包含兩種不同數(shù)據(jù)類(lèi)型的值:基本類(lèi)型值和引用類(lèi)型值。基本類(lèi)型指的是簡(jiǎn)單的數(shù)據(jù)段,而引用類(lèi)型值指那些可...
摘要:之前一篇文章我們?cè)敿?xì)說(shuō)明了變量對(duì)象,而這里,我們將詳細(xì)說(shuō)明作用域鏈。而的作用域鏈,則同時(shí)包含了這三個(gè)變量對(duì)象,所以的執(zhí)行上下文可如下表示。下圖展示了閉包的作用域鏈。其中為當(dāng)前的函數(shù)調(diào)用棧,為當(dāng)前正在被執(zhí)行的函數(shù)的作用域鏈,為當(dāng)前的局部變量。 showImg(https://segmentfault.com/img/remote/1460000008329355);初學(xué)JavaScrip...
摘要:定義函數(shù)表達(dá)式的方式有兩種函數(shù)聲明。不過(guò),這并不是匿名函數(shù)唯一的用途。可以使用命名函數(shù)表達(dá)式來(lái)達(dá)成相同的結(jié)果閉包匿名函數(shù)和閉包是兩個(gè)概念,容易混淆。匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其對(duì)象通常指向通過(guò)改變函數(shù)的執(zhí)行環(huán)境的情況除外。 定義函數(shù)表達(dá)式的方式有兩種: 函數(shù)聲明。它的重要特征就是 函數(shù)聲明提升(function declaration hoisting) 即在執(zhí)行代碼之前會(huì)...
摘要:閉包面試題解由于作用域鏈機(jī)制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個(gè)值,這引起的一個(gè)副作用就是如果內(nèi)部函數(shù)在一個(gè)循環(huán)中,那么變量的值始終為最后一個(gè)值。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第8天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了...
閱讀 683·2023-04-25 18:59
閱讀 1223·2021-09-22 16:00
閱讀 1894·2021-09-22 15:42
閱讀 3602·2021-09-22 15:27
閱讀 1254·2019-08-30 15:54
閱讀 1110·2019-08-30 11:16
閱讀 2457·2019-08-29 16:24
閱讀 834·2019-08-29 12:14