避免DOM对象内存泄漏的使用准则

标签: Web Develop | 发表时间:2011-03-22 13:40 | 作者:[email protected](dh20156) johnny
出处:http://www.v-ec.com/dh20156/

终于,整理了一下在WEB前端脚本开发时因DOM对象造成的内存泄漏原因及解决方案。

避免DOM对象内存泄漏的使用准则

  1. 取自DOM元素的DOM对象,添加属性时,属性值不能是与该DOM对象同作用域下声明的函数,如:a.b=function(){};"

    可选方案:
    1. var b = function(){};(function(){var a = DOMNode;a.b = b;}());
    2. var ret = {b:function(){},init:function(){var a = DOMNode;a.b = ret.b;};
     
  2. 如果该DOM对象被其他对象(如:b)引用,该DOM对象的属性值不能包含有对象b,如:b.push(a);a.b=b;

    可选方案:
    1.var data={};b.push(a);a.setAttribute('GUID') = GUID;data[a.getAttribute('GUID')][b] = b;
     
  3. DOM对象属性值不能显式的引用自己,即,不能在该DOM对象生成的作用域进行显式赋值,如:a.b=a; or a.b = [a]; or a.b = {'x':a};

    可选方案:
    1.var data={};b.push(a);a.setAttribute('GUID') = GUID;data[a.getAttribute('GUID')][b] = b;
     

结论:

  1. 只为DOM对象设置事件类型的属性值(注意避免准则1中的情形)
     
  2. 其他属性通过一个DOM对象的GUID进行关联,存储到一个独立的对象中去
     
  3. 由于做第二步操作会产生人为的内存浪费,所以,需要引入一个适当的垃圾清理机制对其进行清理

DOM对象泄漏测试用例:

<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<div id="x">X容器 ^_^</div>
<button id="y">重置容器X中的内容</button>
<script>
var md = function(module){
    if(!module){return;}
    var dbtn;
    var obtn = [];
    var ret = {
        init:function(){
            /*
            测试1,与DOM对象在同一作用域中申明function对象时
            如果该DOM对象为私有变量,则产生于作用域链中的隐性引用也将计为有效引用,会出现泄漏
            如果该DOM对象为共享对象,则因为每次会对该对象重新赋值,旧的引用自动去除,不会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.onclick = function(){};
            */
           
           
            /*
            测试2,只要函数定义不在DOM对象作用域,不会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.onclick = ret.show;
            */
           
           
            /*
            测试3,属性值内容与DOM对象间无引用,无论该DOM对象是共享对象还是私有变量,不会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.data = ret.data;
            */
           
           
            /*
            测试4,当属性值为显式的对自己的引用,无论DOM对象为私有变量还是共享对象,会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.data = dbtn;
            */
           
           
            /*
            测试5,将此DOM对象设置为另一对象的显式引用
            当属性值包含function类型时,无论DOM对象为私有变量还是共享对象,会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.data = ret.fndata;
            obtn.push(dbtn);
            */
           
           
            /*
            测试6,将此DOM对象设置为另一对象的显式引用
            当属性值为隐性的对自己的引用,不在同一作用域下进行的赋值,无论DOM对象为私有变量还是共享对象,不会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.data = ret.selfdata;
            obtn.push(dbtn);
            */
           
           
            /*
            测试7,将此DOM对象设置为另一对象的显式引用
            当属性值为某对象,而该对象又包含对该DOM对象的引用,无论DOM对象为私有变量还是共享对象,会出现泄漏
            */
            /*
            var dbtn = module.getElementsByTagName('button')[0];
            //dbtn = module.getElementsByTagName('button')[0];
            dbtn.data = ret.cycledata;
            obtn.push(dbtn);
            */
           
           
            /*
            测试8,将此DOM对象设置为另一对象的显式引用
            当属性值不包含function类型时,且不存在对该DOM对象存在引用的对象,则不会出现泄漏
            */
            /*
            //var dbtn = module.getElementsByTagName('button')[0];
            dbtn = module.getElementsByTagName('button')[0];
            dbtn.data = ret.data;
            obtn.push(dbtn);
            */
        },
        show:function(){},
        fndata:{'data':function(){}},
        selfdata:{'dbtn':dbtn},
        cycledata:{'obtn':obtn},
        data:{q:[1,2], s:'string', i:100, b:true}
    };
    return ret;
};
var dx = document.getElementById('x');
var my = md(dx)

var dbtny = document.getElementById('y');
dbtny.onclick = function(){
    dx.innerHTML = '<button>new button '+Math.random()+'</button>';
    my.init();
};
</script>

避免DOM对象泄漏的测试用例:

<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<div id="x">X容器 ^_^</div>
<button id="y">重置容器X中的内容</button>
<script type="text/javascript">
var DNA = {
    pool:{},
    set:function(node, attr, value){
        var GUID = node.getAttribute('GUID');
        if(!GUID){
            GUID = 'GUID'+Math.random();
            node.setAttribute('GUID', GUID);
        }
        if(!this.pool[GUID]){
            this.pool[GUID] = {};
        }
        this.pool[GUID][attr] = value;
    },
    get:function(node, attr){
        var GUID = node.getAttribute('GUID');
        if(!GUID){return;}
        return this.pool[GUID][attr];
    }
};
var dx = document.getElementById('x');
var dbtny = document.getElementById('y');
var obtn = [];
var my = {
    init:function(){
        var dbtn = dx.getElementsByTagName('button')[0];
        obtn.push(dbtn);
        DNA.set(dbtn, 'data', dbtn);
        //DNA.set(dbtn, 'data', obtn);
        //dbtn.data = dbtn;
    }
};
dbtny.onclick = function(){
    dx.innerHTML = '<button>new button '+Math.random()+'</button>';
    my.init();
};
</script>

P.S. JQuery中防止内存泄漏需要确保JQuery不能被多次初始化 - -!

相关 [dom 对象 内存泄漏] 推荐:

避免DOM对象内存泄漏的使用准则

- johnny - W3C标准WEB前端DHTML精英俱乐部
终于,整理了一下在WEB前端脚本开发时因DOM对象造成的内存泄漏原因及解决方案. 避免DOM对象内存泄漏的使用准则. 取自DOM元素的DOM对象,添加属性时,属性值不能是与该DOM对象同作用域下声明的函数,如:a.b=function(){};". 如果该DOM对象被其他对象(如:b)引用,该DOM对象的属性值不能包含有对象b,如:b.push(a);a.b=b;.

内存泄漏

- - CSDN博客系统运维推荐文章
程序申请了堆空间,但是“忘记”释放,导致该块区域在程序结束前无法被再次使用导致的. 泄漏时间长了,就会导致用户空间内存不足,严重的导致死机. 如果泄漏比较严重,很容易察觉;但是有些泄漏很缓慢,不容易察觉,但是软件会运行很长时间后,会慢慢导致严重问题,而且当发现症状的时候,基本上已经是比较晚的时候了,想要识别泄漏,还是可以实现的,本篇文章来聊聊内存操作的原理.

jQuery对象和DOM对象之间的转换实现

- - 码农网
本文主要向大家介绍了jQuery对象和DOM对象之间互相转换的方法,其实转换过程十分简单,一起来看看吧. 在讨论jQuery对象和DOM对象的相互交换之前,先约定好定义变量的风格. 如果获取的对象是jQuery对象,那么在变量前加上$,例如:. var $variable = jQuery对象;. 如果获取的是DOM对象,则定义如下:.

java内存泄漏

- - 编程语言 - ITeye博客
不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址. Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Heap)中分配的,所有对象的回收都是由Java虚拟机通过垃圾回收机制完成的. GC为了能够正确释放对象,会监控每个对象的运行状况,对他们的申请、引用、被引用、赋值等状况进行监控,Java会使用有向图的方法进行管理内存,实时监控对象是否可以达到,如果不可到达,则就将其回收,这样也可以消除引用循环的问题.

前端学习——选择结果为JQuery对象还是DOM对象?

- - CSDN博客Web前端推荐文章
0.前言     在学习和使用javascript过程中经常使用JQuery的选择器,但是在获取到选择结果之后经常“犯迷糊”,需要一个DOM对象时或者一个JQuery对象,这样的尴尬经常遇到. 为了让自己不再迷糊通过博文总结经验教训,希望自己在总结过程中缓慢提高.     【 前端学习——如何修改url name 使用javascript和JQuery】.

浅谈Java--内存泄漏

- - ITeye博客
      JAVA的垃圾回收机制,让许多程序员觉得内存管理不是很重要,但是内存内存泄露的事情恰恰这样的疏忽而发生,特别是对于Android开发,内存管理更为重要,养成良好的习惯,有利于避免内存的泄漏..     这里可以把许多对象和引用看成是有向图,顶点可以是对象也可以是引用,引用关系就是有向边.

Android 解析内存泄漏

- - CSDN博客移动开发推荐文章
1、引用没释放造成的内存泄露.        1.1、注册没取消造成的内存泄露.        这种 Android的内存泄露比纯 Java的内存泄露还要严重,因为其他一些Android程序可能引用我们的Anroid程序的对象(比如注册机制). 即使我们的Android程序已经结束了,但是别的引用程序仍然还有对我们的Android程序的某个对象的引用,泄露的内存依然不能被垃圾回收.

Perfdog玩转内存泄漏

- - 操作系统 - ITeye博客
最近QC同学在跑游戏的过程中发现玩的时间久了游戏会发生闪退,经过搜集信息后排除了功能性bug的. 拿到真机,USB连接,杀掉多余后台进程,打开Perfdog,接下来一顿操作猛如虎,Perfdog具体操作不在赘述,有关perfdog怎么使用的教程可以参考. 此图一出,基本就可以断定内存泄露了,这是正常玩游戏,游戏运行了30分钟的内存趋势图;.

DOM详解

- - CSDN博客推荐文章
 1.XML解析方式分为两种:dom和sax.   (1)dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式.   (2) sax:(Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它.

javaScript DOM使用

- - CSDN博客互联网推荐文章
通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素. 1 修改HTML元素内容. document.write(Date()); //在输入流中直接写 document.getElementById(id).innerHTML=new HTML. //改变已经有的元素内容 document.getElementById("image").src="landscape.jpg";.