详谈JavaScript内存泄漏


Posted in Javascript onNovember 14, 2014

1、什么是闭包、以及闭包所涉及的作用域链这里就不说了。

2、JavaScript垃圾回收机制

     JavaScript不需要手动地释放内存,它使用一种自动垃圾回收机制(garbage collection)。当一个对象无用的时候,即程序中无变量引用这个对象时,就会从内存中释放掉这个变量。

    var s = [ 1, 2 ,3];

    var s = null;

    //这样原始的数组[1 ,2 ,3]就会被释放掉了。

3、循环引用

     三个对象 A 、B 、C

     AàBàC :A的某一属性引用着B,同样C也被B的属性引用着。如果将A清除,那么B、C也被释放。

     AàBàCàB :这里增加了C的某一属性引用B对象,如果这是清除A,那么B、C不会被释放,因为B和C之间产生了循环引用。

    var a = {};

    a.pro = { a:100 };

    a.pro.pro = { b:100 };

    a = null ; 

    //这种情况下,{a:100}和{b:100}就同时也被释放了。

            

    var obj = {};

    obj.pro = { a : 100 };

    obj.pro.pro = { b : 200 };

    var two = obj.pro.pro;

    obj = null;    

    //这种情况下 {b:200}不会被释放掉,而{a:100}被释放了。

 

4、循环引用和闭包

    function outer(){

        var obj = {};

        function inner(){ 

            //这里引用了obj对象

        }

        obj.inner = inner;

    }

这是一种及其隐蔽的循环引用,。当调用一次outer时,就会在其内部创建obj和inner两个对象,obj的inner属性引用了inner;同样inner也引用了obj,这是因为obj仍然在innerFun的封闭环境中,准确的讲这是由于JavaScript特有的“作用域链”。
因此,闭包非常容易创建循环引用,幸运的是JavaScript能够很好的处理这种循环引用。

5、IE中的内存泄漏

    IE中的内存泄漏有好几种,这里有详细的解释(http://msdn.microsoft.com/en-us/library/bb250448.aspx)。

    这里只讨论其中一种,即循环引用所造成的内存泄漏,因为,这是一种最普遍的情况。

    当在DOM元素或一个ActiveX对象与普通JavaScript对象之间存在循环引用时,IE在释放这类变量时存在特殊的困难,最好手动切断循环引用,这个bug在IE 7中已经被修复了(http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html)。

   “IE 6 suffered from memory leaks when a circular reference between several objects, among which at least one DOM node, was created. This problem has been solved in IE 7. ”

    如果上面的例子(第4点)中obj引用的不是一个JavaScript Function对象(inner),而是一个ActiveX对象或Dom元素,这样在IE中所形成的循环引用无法得到释放。

    function init(){

        var elem = document.getElementByid( 'id' );

        elem.onclick = function(){

            alert('rain-man');

            //这里引用了elem元素

        };

    }

Elem引用了它的click事件的监听函数,同样该函数通过其作用域链也引用回了elem元素。这样在IE中即使离开当前页面也不会释放这些循环引用。

6、解决方法

   基本的方法就是手动清除这种循环引用,下面一个十分简单的例子,实际应用时可以自己构建一个addEvent()函数,并且在window的unload事件上对所有事件绑定进行清除。

    function outer(){

        var one = document.getElementById( 'one' );

        one.onclick = function(){};

    }

    window.onunload = function(){

        var one = document.getElementById( 'one' );

        one.onclick = null;

    };

 其它方法(by:Douglas Crockford)

/**

 * 遍历某一元素节点及其所有后代元素

 *

 * @param Elem node  所要清除的元素节点

 * @param function func  进行处理的函数

 * 

 */

function walkTheDOM(node, func) {

    func(node); 

    node = node.firstChild; 

    while (node) { 

        walkTheDOM(node, func); 

        node = node.nextSibling; 

    } 

} 

/**

 * 清除dom节点的所有引用,防止内存泄露

 *

 * @param Elem node  所要清除的元素节点

 * 

 */

function purgeEventHandlers(node) {

    walkTheDOM(node, function (e) {

        for (var n in e) {            

            if (typeof e[n] === 

                    'function') {

                e[n] = null;

            }

        }

    });

以上就是JavaScript内存泄漏的相关内容以及解决方案了,有需要的小伙伴可以参考下

Javascript 相关文章推荐
js几个不错的函数 $$()
Oct 09 Javascript
基于jQuery实现图片的前进与后退功能
Apr 24 Javascript
Ajax请求在数据量大的时候出现超时的解决方法
Feb 27 Javascript
JS的事件绑定深入认识
Jun 26 Javascript
JQuery表格拖动调整列宽效果(自己动手写的)
Sep 01 Javascript
使用js画图之正弦曲线
Jan 12 Javascript
分享一个插件实现水珠自动下落效果
Jun 01 Javascript
jQuery实现鼠标经过显示动画边框特效
Mar 24 jQuery
微信小程序实现的一键复制功能示例
Apr 24 Javascript
如何基于JavaScript判断图片是否加载完成
Dec 28 Javascript
vue项目中js-cookie的使用存储token操作
Nov 13 Javascript
Vue.js中v-bind指令的用法介绍
Mar 13 Vue.js
js与C#进行时间戳转换
Nov 14 #Javascript
jquery ui bootstrap 实现自定义风格
Nov 14 #Javascript
使用node.js 制作网站前台后台
Nov 13 #Javascript
JavaScript 作用域链解析
Nov 13 #Javascript
jQuery $命名冲突解决方案汇总
Nov 13 #Javascript
js获取字符串最后一位方法汇总
Nov 13 #Javascript
实现js保留小数点后N位的代码
Nov 13 #Javascript
You might like
PHP 调试工具Debug Tools
2011/04/30 PHP
关于更改Zend Studio/Eclipse代码风格主题的介绍
2013/06/23 PHP
走出JavaScript初学困境—js初学
2008/12/29 Javascript
基于Jquery的将DropDownlist的选中值赋给label的实现代码
2011/05/06 Javascript
用js小类库获取浏览器的高度和宽度信息
2012/01/15 Javascript
统计jQuery中各字符串出现次数的工具
2012/05/03 Javascript
没有document.getElementByName方法
2013/08/19 Javascript
Javascript 高阶函数使用介绍
2015/06/15 Javascript
高性能JavaScript循环语句和条件语句
2016/01/20 Javascript
jQuery web 组件 后台日历价格、库存设置的代码
2016/10/14 Javascript
基于JS实现的随机数字抽签实例
2016/12/08 Javascript
详解NodeJs支付宝移动支付签名及验签
2017/01/06 NodeJs
关于AngularJs数据的本地存储详解
2017/01/20 Javascript
动态加载JavaScript文件的3种方式
2018/05/05 Javascript
vue生成文件本地打开查看效果的实例
2018/09/06 Javascript
vue中使用微信公众号js-sdk踩坑记录
2019/03/29 Javascript
微信打开网址添加在浏览器中打开提示的办法
2019/05/20 Javascript
深入浅出vue图片路径的实现
2019/09/04 Javascript
jquery实现简单每周轮换的日历
2020/09/10 jQuery
vue基于Echarts的拖拽数据可视化功能实现
2020/12/04 Vue.js
[03:57]2016完美“圣”典风云人物:rOtk专访
2016/12/09 DOTA
用Python遍历C盘dll文件的方法
2015/05/06 Python
Python字符串格式化输出方法分析
2016/04/13 Python
python探索之BaseHTTPServer-实现Web服务器介绍
2017/10/28 Python
python 把文件中的每一行以数组的元素放入数组中的方法
2018/04/29 Python
利用pandas进行大文件计数处理的方法
2018/07/25 Python
Python进阶之使用selenium爬取淘宝商品信息功能示例
2019/09/16 Python
Django 自定义分页器的实现代码
2019/11/24 Python
Python求解排列中的逆序数个数实例
2020/05/03 Python
实例讲解CSS3中Transform的perspective属性的用法
2016/04/22 HTML / CSS
html5 视频播放解决方案
2016/11/06 HTML / CSS
华为菲律宾官方网站:HUAWEI Philippines
2021/02/23 全球购物
计算机大学生的自我评价
2013/10/15 职场文书
大学社团活动总结
2014/04/26 职场文书
2016年十一促销广告语
2016/01/28 职场文书
个人房屋租赁合同(标准范本)
2019/09/16 职场文书