複製代碼 代碼如下:function fors(){
obj_a = obj_b;
obj_b.attr = obj_a;
}
複製代碼 代碼如下:function fors(){
obj_b = {};
obj_b.attr = obj_b;
}
上面是兩個個很顯示的循環參考,IE中產生了記憶體泄露,由於IE的記憶體回收機制,導至會長期佔用記憶體而不能釋放。
但閉包的記憶體泄露,有些隱蔽。因為閉包的循環參考,是間接的。 複製代碼 代碼如下:function iememery(){
var js_obj = document.createElement("div");
js_obj.oncontextmenu = function(){ return false;}
}
<body onload="iememery()">
從表面上看,沒有任何循環參考。但上面是一個閉包,根據閉包的特性,內建函式有權訪問外部函數的變數對象。所以當iememery()執行之後:
js_obj是一個DOM元素的引用,DOM元素它長期在網頁當中,不會消失,而這個DOM元素的一屬性oncontextmenu,又是內部的函數引用(閉包),而這個匿名函數又和js_obj之間有隱藏的關聯(範圍鏈)
所以形成了一個,循環參考.即:
js_obj.oncontextmenu 間接引用到 js_obj 也就是說,這個對象的一個屬性,又間接的引用了自己。
只要有循環參考,就會在IE下產生記憶體泄露。開啟你的windows工作管理員,在IE中不停重新整理含有這個代碼的html頁面,看看Iexploer進程的記憶體佔用情況,一直上升,且不會自動回收(降低);
解決辦法: 複製代碼 代碼如下:function iememery(){
var js_obj = document.createElement("div");
js_obj.oncontextmenu = function(){ return false;}; js_obj.oncontextmenu = null;//加上這句,斷開引用 }
當IE中發生js對象與dom對象直接的循環參考,並且之後沒有引用指向他們,
如果是IE 6, 記憶體流失,直到關閉IE進程為止
如果是IE 7,記憶體流失, 直到離開當前頁面為止
如果是IE 8, GC回收器回收他們的記憶體,無論當前是不是compatibility模式。
之前的IE js引擎裡的GC回收器只能處理js對象,不能處理DOM對象。