添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
var button = document.getElementById('button'); function onClick(event) { button.innerHTML = 'text'; button.addEventListener('click', onClick);

给元素button添加了一个事件处理器onClick, 而处理器里面使用了button的引用。而老版本的 IE 是无法检测 DOM 节点与 JavaScript 代码之间的循环引用,因此会导致内存泄漏

如今,现代的浏览器(包括 IE 和 Microsoft Edge)使用了更先进的垃圾回收算法,已经可以正确检测和处理循环引用了。换言之,回收节点内存时,不必非要调用 removeEventListener 了。

另外介绍一下常见的容易导致内存泄漏的点

  • 意外的全局变量 (如果必须使用全局变量存储大量数据时,确保用完以后把它设置为 null 或者重新定义。与全局变量相关的增加内存消耗的一个主因是缓存。缓存数据是为了重用,缓存必须有一个大小上限才有用。)
  • 被遗忘的计时器,比如下面示例代码, 尽管这个定时器不再需要,里面的回调也不再需要,可是计时器回调函数并没有被回收,这样someResource,如果存储了大量的数据,也是无法被回收。 因此需要把定时器清除。
  • var someResource = getData();
    setInterval(function() {
        var node = document.getElementById('Node');
        if(node) {
            // 处理 node 和 someResource
            node.innerHTML = JSON.stringify(someResource));
    }, 1000);
    
  • 脱离DOM的引用(当你保存了一个dom的引用,然后将该dom从html中删除后,你应该将这个引用赋为null,否则GC不会回收,这个dom仍然在内存中。保存 DOM 元素引用的时候,要小心谨慎。
  • var elements = {
        button: document.getElementById('button'),
        image: document.getElementById('image'),
        text: document.getElementById('text')
    function doStuff() {
        image.src = 'http://some.url/image';
        button.click();
        console.log(text.innerHTML);
        // 更多逻辑
    function removeButton() {
        // 按钮是 body 的后代元素
        document.body.removeChild(document.getElementById('button'));
        // 此时,仍旧存在一个全局的 #button 的引用
        // elements 字典。button 元素仍旧在内存中,不能被 GC 回收。
    

    闭包包含这外面函数的活动对象,无法被GC回收。

    分类:
    前端
    标签: