详谈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 字符串转化成数字的代码
Jun 29 Javascript
JQuery实现简单时尚快捷的气泡提示插件
Dec 20 Javascript
js实现的点击数量加一可操作数据库
May 09 Javascript
js阻止事件追加的具体实现
Oct 15 Javascript
JQuery异步获取返回值中文乱码的解决方法
Jan 29 Javascript
Js和JQuery获取鼠标指针坐标的实现代码分享
May 25 Javascript
深入剖析javascript中的exec与match方法
May 18 Javascript
总结Javascript中的隐式类型转换
Aug 24 Javascript
如何在Angular应用中创建包含组件方法示例
Mar 23 Javascript
jquery操作select常见方法大全【7种情况】
May 28 jQuery
微信小程序实现蒙版弹出窗功能
Sep 17 Javascript
解决elementUI 切换tab后 el_table 固定列下方多了一条线问题
Jul 19 Javascript
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截断标题且兼容utf8和gb2312编码
2013/09/22 PHP
PHP实现对文本数据库的常用操作方法实例演示
2014/07/04 PHP
php实现图片转换成ASCII码的方法
2015/04/03 PHP
php array_walk 对数组中的每个元素应用用户自定义函数详解
2016/11/18 PHP
巧妙破除网页右键禁用的十大绝招
2006/08/12 Javascript
javascript 页面只自动刷新一次
2009/07/10 Javascript
XENON基于JSON变种
2010/07/27 Javascript
Fixie.js 自动填充内容的插件
2012/06/28 Javascript
利用try-catch判断变量是已声明未声明还是未赋值
2014/03/12 Javascript
事件委托与阻止冒泡阻止其父元素事件触发
2014/09/02 Javascript
AngularJS学习笔记之ng-options指令
2015/06/16 Javascript
js实现显示当前状态的导航效果代码
2015/08/28 Javascript
Bootstrap每天必学之栅格系统(布局)
2015/11/25 Javascript
jquery对复选框(checkbox)的操作汇总
2016/01/13 Javascript
JavaScript浮点数及运算精度调整详解
2016/10/21 Javascript
AngularJS中指令的四种基本形式实例分析
2016/11/22 Javascript
NodeJS测试框架mocha入门教程
2017/03/28 NodeJs
webpack4.x开发环境配置详解
2018/08/04 Javascript
vue webpack重写cookie路径的方法
2019/07/10 Javascript
Vue + Scss 动态切换主题颜色实现换肤的示例代码
2020/04/27 Javascript
[44:15]国士无双DOTA2 6.82版本详解(上)
2014/09/28 DOTA
[02:49]2018DOTA2亚洲邀请赛主赛事决赛日战况回顾 Mineski鏖战5局夺得辉耀
2018/04/10 DOTA
Python threading多线程编程实例
2014/09/18 Python
Python实现屏幕截图的代码及函数详解
2016/10/01 Python
Python基于递归算法求最小公倍数和最大公约数示例
2018/07/27 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
如何在Django配置文件里配置session链接
2019/08/06 Python
Python3 JSON编码解码方法详解
2019/09/06 Python
HTML5 微格式和相关的属性名称
2010/02/10 HTML / CSS
中国领先的汽车保养服务平台:途虎养车
2019/10/18 全球购物
求职信的要素有哪些呢
2013/12/26 职场文书
十岁生日父母答谢词
2014/01/18 职场文书
销售员岗位职责
2014/06/09 职场文书
医院保洁员岗位职责
2015/02/13 职场文书
2015年度销售个人工作总结
2015/03/31 职场文书
2016年小学生新年寄语
2015/08/18 职场文书