详谈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 相关文章推荐
jQuery 使用手册(二)
Sep 23 Javascript
3种不同方式的焦点图轮播特效分享
Oct 30 Javascript
封装的jquery翻页滚动(示例代码)
Nov 18 Javascript
javascript在子页面中函数无法调试问题解决方法
Jan 17 Javascript
使用js判断当前时区TimeZone是否是夏令时
Feb 23 Javascript
node.js中的forEach()是同步还是异步呢
Jan 29 Javascript
js实现上传图片预览的方法
Feb 09 Javascript
实用jquery操作表单元素的简单代码
Jul 04 Javascript
JSONP和批量操作功能的实现方法
Aug 21 Javascript
KnockoutJS 3.X API 第四章之数据控制流foreach绑定
Oct 10 Javascript
详解用vue-cli来搭建vue项目和webpack
Apr 20 Javascript
js+canvas实现验证码功能
Sep 21 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类分享
2014/02/07 PHP
php强制文件下载而非在浏览器打开的自定义函数分享
2014/05/08 PHP
php实现的简单中文验证码功能示例
2017/01/03 PHP
jQuery操作select的实例代码
2012/06/14 Javascript
使用正则表达式的格式化与高亮显示json字符串
2014/12/03 Javascript
d3.js实现简单的网络拓扑图实例代码
2016/11/06 Javascript
轻松理解Javascript变量的相关问题
2017/01/20 Javascript
Jquery根据浏览器窗口改变调整大小的方法
2017/02/07 Javascript
JavaScript的六种继承方式(推荐)
2017/06/26 Javascript
关于jQuery.ajax()的jsonp碰上post详解
2017/07/02 jQuery
原生javascript AJAX 三级联动的实现代码
2018/05/04 Javascript
js实现多图和单图上传显示
2019/12/18 Javascript
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
[01:21:07]EG vs Liquid 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
总结用Pdb库调试Python的方式及常用的命令
2016/08/18 Python
virtualenv实现多个版本Python共存
2017/08/21 Python
Python自定义装饰器原理与用法实例分析
2018/07/16 Python
PyQt Qt Designer工具的布局管理详解
2019/08/07 Python
Python实现银行账户资金交易管理系统
2020/01/03 Python
Pytorch技巧:DataLoader的collate_fn参数使用详解
2020/01/08 Python
基于python3的socket聊天编程
2020/02/17 Python
浅谈matplotlib.pyplot与axes的关系
2020/03/06 Python
python网络编程:socketserver的基本使用方法实例分析
2020/04/09 Python
python中pathlib模块的基本用法与总结
2020/08/17 Python
CSS3实现鼠标悬停显示扩展内容
2016/08/24 HTML / CSS
如何写毕业求职自荐信
2013/11/06 职场文书
大型营销活动计划书
2014/04/28 职场文书
七一党日活动总结
2014/07/08 职场文书
2014应届本科生自我评价
2014/09/13 职场文书
学生不讲诚信检讨书
2014/09/29 职场文书
简历自我评价模板
2015/03/11 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
职场:企业印章管理制度(模板)
2019/10/18 职场文书
Python利器openpyxl之操作excel表格
2021/04/17 Python
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
2022/04/24 Java/Android
Pandas实现批量拆分与合并Excel的示例代码
2022/05/30 Python