摘要:閉包的本質(zhì)是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。這就可能造成大量內(nèi)存得不到回收內(nèi)存泄露,因為它們的引用次數(shù)永遠(yuǎn)不可能是。早期的版本里采用是計數(shù)的垃圾回收機制,閉包導(dǎo)致內(nèi)存泄露的一個原因就是這個算法的一個缺陷。
1.閉包的概念
閉包:指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。
閉包的本質(zhì)是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。
例1:
function outer(){ var a=1; function inner(){ a++; alert(a); } return inner; } var f1=outer();//創(chuàng)建了一個閉包,f1能訪問outer函數(shù)中的變量 f1();//彈出2.
這段代碼的特點在于:
1.函數(shù)inner嵌套在函數(shù)outer內(nèi)部
2.函數(shù)outer返回函數(shù)inner,并將值賦給了f1
例2:
// 實現(xiàn)累加:方式1 var a = 0; var add = function(){ a++; console.log(a) } add(); add(); //方式2 :閉包 var add = (function(){ var a = 0; return function(){ a++; console.log(a); } })(); console.log(a); //undefined add(); add(); //方式2的優(yōu)點:減少全局變量,將變量私有化3.閉包與變量的關(guān)系
閉包只能取得包含函數(shù)中任何變量的最后一個值。
例:
function f1() { var res = new Array(); for(var i=0;i<10;i++){ res[i] = function() { alert(i); }; } return res; } var f2 = f1(); var f2 = f1(); f2[0]();//alert 10 //并不會返回一次彈出0-9的函數(shù)數(shù)組,而是彈出10個10的函數(shù)數(shù)組,因為res中每個函數(shù)的作用域中都保存著f1()的活動對象,引用的是同一個變量i,當(dāng)f1()返回后i的值為10
解決方法:
function f1() { var res = new Array(); for(var i=0;i<10;i++){ res[i] = (function(num) { return function (){ alert(num); } })(i);//函數(shù)參數(shù)按值傳遞 } return res; } var f2 = f1(); var f2 = f1(); f2[0]();//alert 04.內(nèi)存泄露及解決方案
垃圾回收機制
說到內(nèi)存管理,自然離不開JS中的垃圾回收機制,有兩種策略來實現(xiàn)垃圾回收:標(biāo)記清除 和 引用計數(shù);
標(biāo)記清除:垃圾收集器在運行的時候會給存儲在內(nèi)存中的所有變量都加上標(biāo)記,然后,它會去掉環(huán)境中的變量的標(biāo)記和被環(huán)境中的變量引用的變量的標(biāo)記,此后,如果變量再被標(biāo)記則表示此變量準(zhǔn)備被刪除。 2008年為止,IE,F(xiàn)irefox,opera,chrome,Safari的javascript都用使用了該方式;
引用計數(shù):跟蹤記錄每個值被引用的次數(shù),當(dāng)聲明一個變量并將一個引用類型的值賦給該變量時,這個值的引用次數(shù)就是1,如果這個值再被賦值給另一個變量,則引用次數(shù)加1。相反,如果一個變量脫離了該值的引用,則該值引用次數(shù)減1,當(dāng)次數(shù)為0時,就會等待垃圾收集器的回收。
這個方式存在一個比較大的問題就是循環(huán)引用,就是說A對象包含一個指向B的指針,對象B也包含一個指向A的引用。 這就可能造成大量內(nèi)存得不到回收(內(nèi)存泄露),因為它們的引用次數(shù)永遠(yuǎn)不可能是 0 。早期的IE版本里(ie4-ie6)采用是計數(shù)的垃圾回收機制,閉包導(dǎo)致內(nèi)存泄露的一個原因就是這個算法的一個缺陷。
我們知道,IE中有一部分對象并不是原生額javascript對象,例如,BOM和DOM中的對象就是以COM對象的形式實現(xiàn)的,而COM對象的垃圾回收機制采用的就是引用計數(shù)。因此,雖然IE的javascript引擎采用的是標(biāo)記清除策略,但是訪問COM對象依然是基于引用計數(shù)的,因此只要在IE中設(shè)計COM對象就會存在循環(huán)引用的問題!
例子:
window.onload = function(){ var ele = document.getElementById("id"); ele.onclick = function(){ alert(ele.id); } }
這段代碼為什么會造成內(nèi)存泄露?
ele.onclick = function(){ alert(ele.id); }
執(zhí)行這段代碼的時候,將匿名函數(shù)對象賦值給ele的onclick屬性;然后匿名函數(shù)內(nèi)部又引用了ele對象,存在循環(huán)引用,所以不能被回收。
解決方法:
window.onload = function(){ var ele = document.getElementById("id"); var id = ele.id; //解除循環(huán)引用 ele.onclick = function(){ alert(id); } ele = null; // 將閉包引用的外部函數(shù)中活動對象清除 }5.總結(jié)閉包的優(yōu)缺點
優(yōu)點:
當(dāng)需要一個變量常駐內(nèi)存時,閉包可以實現(xiàn)一個變量常駐內(nèi)存 (如果多了就占用內(nèi)存了)
避免全局變量的污染
私有化變量
缺點:
因為閉包會攜帶包含它的函數(shù)的作用域,因此會比其他函數(shù)占用更多的內(nèi)存
引起內(nèi)存泄露
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/79029.html
摘要:解決方式是,當(dāng)我們不使用它們的時候,手動切斷鏈接淘汰把和對象轉(zhuǎn)為了真正的對象,避免了使用這種垃圾收集策略,消除了以下常見的內(nèi)存泄漏的主要原因。以上參考資料高程垃圾收集類內(nèi)存泄漏及如何避免內(nèi)存泄露及解決方案詳解類內(nèi)存泄漏及如何避免 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1ft1ikzcqzqj30ka0et77a.jpg); 前言 起...
摘要:垃圾回收內(nèi)存管理實踐先通過一個來看看在中進行垃圾回收的過程是怎樣的內(nèi)存泄漏識別在環(huán)境里提供了方法用來查看當(dāng)前進程內(nèi)存使用情況,單位為字節(jié)中保存的進程占用的內(nèi)存部分,包括代碼本身棧堆。 showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技術(shù)棧 | https:...
摘要:的內(nèi)存泄漏對于這門語言的使用者來說,大多數(shù)的使用者的內(nèi)存管理意識都不強。內(nèi)存泄漏的定義指由于疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。 javascript的內(nèi)存泄漏 對于JavaScript這門語言的使用者來說,大多數(shù)的使用者的內(nèi)存管理意識都不強。因為JavaScript一直以來都只作為在網(wǎng)頁上使用的腳本語言,而網(wǎng)頁往往都不會長時間的運行,所以使用者對JavaScript的...
摘要:介紹瀏覽器的具有自動垃圾回收機制,也就是說,執(zhí)行環(huán)境會負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。中的內(nèi)存泄漏問題程序的內(nèi)存溢出后,會使某一段函數(shù)體永遠(yuǎn)失效取決于當(dāng)時的代碼運行到哪一個函數(shù),通常表現(xiàn)為程序突然卡死或程序出現(xiàn)異常。 showImg(https://segmentfault.com/img/remote/1460000018932880?w=4400&h=3080); 1. 介紹 瀏...
摘要:引擎對堆內(nèi)存中的對象進行分代管理新生代存活周期較短的對象,如臨時變量字符串等。內(nèi)存泄漏對于持續(xù)運行的服務(wù)進程,必須及時釋放不再用到的內(nèi)存。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,今天是第4天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃...
閱讀 2884·2021-11-23 09:51
閱讀 2160·2021-10-13 09:40
閱讀 1621·2021-09-30 10:01
閱讀 699·2021-09-26 09:46
閱讀 2434·2021-09-23 11:55
閱讀 1589·2021-09-10 10:51
閱讀 2498·2021-09-09 09:33
閱讀 2317·2019-08-29 17:25