IE9以前的版本對JScript對象和COM對象使用不一樣的垃圾回收例程(COM對象採用「引用計數」收集策略),所以閉包在IE的這些版本中會致使一些特殊問題。具體來講,若是閉包的做用域中保存着一個HTML元素,那麼就意味着該元素將沒法被銷燬。來看下面的例子:javascript
function assignHandler() { var elem = document.getElementById('elem_id'); elem.onclick = function(evt) { alert(elem.id); }; }
以上代碼建立了一個做爲elem元素事件處理程序的閉包,而這個閉包則又建立了一個循環引用。因爲匿名函數保存了一個對assignHandler()的活動對象的引用,所以就會致使沒法減小elem的引用數。只要匿名函數存在,elem的引用數至少也是1,所以它所佔用的內存就永遠不會被回收。能夠將上面的代碼稍做修改一下就能夠解決:html
function assignHandler() { var elem = document.getElementById('elem_id'); var elem_id = elem.id; elem.onclick = function(evt) { alert(elem_id); }; elem = null; }
經過把elem.id的一個副本保存在一個變量中,而且在閉包中引用該變量消除了循環引用。但僅僅作到這一步,仍是不能解決內存泄露問題。
「閉包會引用包含函數的整個活動對象,而其中就包含着elem。即便閉包不直接引用elem,包含函數的活動對象中也仍然會保存一個引用。所以,有必要把elem設置爲null。這樣就能解除對DOM對象的引用,順利地減小其引用數,確保正常回收其佔用的內存」