转:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScriptjavascript
使用闭包的一个坏处是,在 IE 浏览器中它会很容易致使内存泄露。JavaScript 是一种具备垃圾回收机制的语言——对象在被建立的时候分配内存,而后当指向这个对象的引用计数为零时,浏览器会回收内存。宿主环境提供的对象都是按照这种方法被处理的。java
浏览器主机须要处理大量的对象来描绘一个正在被展示的 HTML 页面——DOM 对象。浏览器负责管理它们的内存分配和回收。浏览器
IE 浏览器有本身的一套垃圾回收机制,这套机制与 JavaScript 提供的垃圾回收机制进行交互时,可能会发生内存泄露。数据结构
在 IE 中,每当在一个 JavaScript 对象和一个本地对象之间造成循环引用时,就会发生内存泄露。以下所示:闭包
function leakMemory() { var el = document.getElementById('el'); var o = { 'el': el }; el.o = o; }
这段代码的循环引用会致使内存泄露:IE 不会释放被 el
和 o
使用的内存,直到浏览器被完全关闭并重启后。函数
这个例子每每没法引发人们的重视:通常只会在长时间运行的应用程序中,或者由于巨大的数据量和循环中致使内存泄露发生时,内存泄露才会引发注意。this
不过通常也不多发生如此明显的内存泄露现象——一般泄露的数据结构有多层的引用(references),每每掩盖了循环引用的状况。code
闭包很容易发生无心识的内存泄露。以下所示:对象
function addHandler() { var el = document.getElementById('el'); el.onclick = function() { el.style.backgroundColor = 'red'; } }
这段代码建立了一个元素,当它被点击的时候变红,但同时它也会发生内存泄露。为何?由于对 el
的引用不当心被放在一个匿名内部函数中。这就在 JavaScript 对象(这个内部函数)和本地对象之间(el
)建立了一个循环引用。blog
这个问题有不少种解决方法,最简单的一种是不要使用 el
变量:
function addHandler(){ document.getElementById('el').onclick = function(){ this.style.backgroundColor = 'red'; }; }
另一种避免闭包的好方法是在 window.onunload
事件发生期间破坏循环引用。不少事件库都能完成这项工做。注意这样作将使 Firefox 中的 bfcache 没法工做。因此除非有其余必要的缘由,最好不要在 Firefox 中注册一个onunload
的监听器。