詳談JavaScript內(nèi)存泄漏
1、什么是閉包、以及閉包所涉及的作用域鏈這里就不說了。
2、JavaScript垃圾回收機(jī)制
JavaScript不需要手動(dòng)地釋放內(nèi)存,它使用一種自動(dòng)垃圾回收機(jī)制(garbage collection)。當(dāng)一個(gè)對象無用的時(shí)候,即程序中無變量引用這個(gè)對象時(shí),就會(huì)從內(nèi)存中釋放掉這個(gè)變量。
var s = [ 1, 2 ,3];
var s = null;
//這樣原始的數(shù)組[1 ,2 ,3]就會(huì)被釋放掉了。
3、循環(huán)引用
三個(gè)對象 A 、B 、C
AàBàC :A的某一屬性引用著B,同樣C也被B的屬性引用著。如果將A清除,那么B、C也被釋放。
AàBàCàB :這里增加了C的某一屬性引用B對象,如果這是清除A,那么B、C不會(huì)被釋放,因?yàn)锽和C之間產(chǎn)生了循環(huán)引用。
var a = {};
a.pro = { a:100 };
a.pro.pro = { b:100 };
a = null ;
//這種情況下,{a:100}和{b:100}就同時(shí)也被釋放了。
var obj = {};
obj.pro = { a : 100 };
obj.pro.pro = { b : 200 };
var two = obj.pro.pro;
obj = null;
//這種情況下 {b:200}不會(huì)被釋放掉,而{a:100}被釋放了。
4、循環(huán)引用和閉包
function outer(){
var obj = {};
function inner(){
//這里引用了obj對象
}
obj.inner = inner;
}
這是一種及其隱蔽的循環(huán)引用,。當(dāng)調(diào)用一次outer時(shí),就會(huì)在其內(nèi)部創(chuàng)建obj和inner兩個(gè)對象,obj的inner屬性引用了inner;同樣inner也引用了obj,這是因?yàn)閛bj仍然在innerFun的封閉環(huán)境中,準(zhǔn)確的講這是由于JavaScript特有的“作用域鏈”。
因此,閉包非常容易創(chuàng)建循環(huán)引用,幸運(yùn)的是JavaScript能夠很好的處理這種循環(huán)引用。
5、IE中的內(nèi)存泄漏
IE中的內(nèi)存泄漏有好幾種,這里有詳細(xì)的解釋(http://msdn.microsoft.com/en-us/library/bb250448.aspx)。
這里只討論其中一種,即循環(huán)引用所造成的內(nèi)存泄漏,因?yàn)椋@是一種最普遍的情況。
當(dāng)在DOM元素或一個(gè)ActiveX對象與普通JavaScript對象之間存在循環(huán)引用時(shí),IE在釋放這類變量時(shí)存在特殊的困難,最好手動(dòng)切斷循環(huán)引用,這個(gè)bug在IE 7中已經(jīng)被修復(fù)了(http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html)。
“IE 6 suffered from memory leaks when a circular reference between several objects, among which at least one DOM node, was created. This problem has been solved in IE 7. ”
如果上面的例子(第4點(diǎn))中obj引用的不是一個(gè)JavaScript Function對象(inner),而是一個(gè)ActiveX對象或Dom元素,這樣在IE中所形成的循環(huán)引用無法得到釋放。
function init(){
var elem = document.getElementByid( 'id' );
elem.onclick = function(){
alert('rain-man');
//這里引用了elem元素
};
}
Elem引用了它的click事件的監(jiān)聽函數(shù),同樣該函數(shù)通過其作用域鏈也引用回了elem元素。這樣在IE中即使離開當(dāng)前頁面也不會(huì)釋放這些循環(huán)引用。
6、解決方法
基本的方法就是手動(dòng)清除這種循環(huán)引用,下面一個(gè)十分簡單的例子,實(shí)際應(yīng)用時(shí)可以自己構(gòu)建一個(gè)addEvent()函數(shù),并且在window的unload事件上對所有事件綁定進(jìn)行清除。
function outer(){
var one = document.getElementById( 'one' );
one.onclick = function(){};
}
window.onunload = function(){
var one = document.getElementById( 'one' );
one.onclick = null;
};
其它方法(by:Douglas Crockford)
/**
* 遍歷某一元素節(jié)點(diǎn)及其所有后代元素
*
* @param Elem node 所要清除的元素節(jié)點(diǎn)
* @param function func 進(jìn)行處理的函數(shù)
*
*/
function walkTheDOM(node, func) {
func(node);
node = node.firstChild;
while (node) {
walkTheDOM(node, func);
node = node.nextSibling;
}
}
/**
* 清除dom節(jié)點(diǎn)的所有引用,防止內(nèi)存泄露
*
* @param Elem node 所要清除的元素節(jié)點(diǎn)
*
*/
function purgeEventHandlers(node) {
walkTheDOM(node, function (e) {
for (var n in e) {
if (typeof e[n] ===
'function') {
e[n] = null;
}
}
});
以上就是JavaScript內(nèi)存泄漏的相關(guān)內(nèi)容以及解決方案了,有需要的小伙伴可以參考下
相關(guān)文章
使一個(gè)函數(shù)作為另外一個(gè)函數(shù)的參數(shù)來運(yùn)行的javascript代碼
使一個(gè)函數(shù)作為另外一個(gè)函數(shù)的參數(shù)來運(yùn)行的javascript代碼...2007-08-08詳解Html a標(biāo)簽中href和onclick用法、區(qū)別、優(yōu)先級(jí)別
本文主要分享一篇關(guān)于Html A標(biāo)簽中href和onclick用法、區(qū)別、優(yōu)先級(jí)別,具有很好的參考價(jià)值,有需要了解的朋友可以看看2017-01-01JS實(shí)現(xiàn)簡單控制視頻播放倍速的實(shí)例代碼
這篇文章主要介紹了通過JS來實(shí)現(xiàn)簡單控制視頻播放倍速,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04js下為表格內(nèi)部動(dòng)態(tài)添加行的代碼
最近的一個(gè)項(xiàng)目中在保存表單數(shù)據(jù)時(shí),要用到一個(gè)動(dòng)態(tài)添加行的功能。平時(shí)動(dòng)態(tài)添加行只是在表格的最下面添加,現(xiàn)在在表格中間動(dòng)態(tài)添加行,而且表格內(nèi)部是包含并且單元格的,其實(shí)很簡單,下面貼出代碼。2010-06-06原生Js與jquery的多組處理, 僅展開一個(gè)區(qū)塊的折疊效果
同一個(gè)頁面, 有多組(不固定), 每組區(qū)塊數(shù)量不一定一樣的小區(qū)塊. 要求每次只展開一個(gè)區(qū)塊,需要的朋友可以參考下。2011-01-01JavaScript實(shí)現(xiàn)將數(shù)組數(shù)據(jù)添加到Select下拉框的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)將數(shù)組數(shù)據(jù)添加到Select下拉框的方法,涉及javascript數(shù)組操作及頁面元素動(dòng)態(tài)賦值的相關(guān)技巧,需要的朋友可以參考下2015-08-08three.js 實(shí)現(xiàn)露珠滴落動(dòng)畫效果的示例代碼
這篇文章主要介紹了three.js 實(shí)現(xiàn)露珠滴落動(dòng)畫效果的示例代碼,非常不錯(cuò),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03