详谈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 相关文章推荐
JavaScript定义类或函数的几种方式小结
Jan 09 Javascript
javascript中style.left和offsetLeft的用法说明
Mar 07 Javascript
javascript中Date对象的getDay方法使用指南
Dec 22 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
Mar 02 Javascript
深入理解JavaScript的React框架的原理
Jul 02 Javascript
Ajax分页插件Pagination从前台jQuery到后端java总结
Jul 22 Javascript
利用fecha进行JS日期处理
Nov 21 Javascript
深入理解JavaScript中的尾调用(Tail Call)
Feb 07 Javascript
bootstrap栅格系统示例代码分享
May 22 Javascript
JS实现的透明度渐变动画效果示例
Apr 28 Javascript
jQuery实现动态加载(按需加载)javascript文件的方法分析
May 31 jQuery
vue实现锚点定位功能
Jun 29 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
Snoopy类使用小例子
2008/04/15 PHP
php高级编程-函数-郑阿奇
2011/07/04 PHP
PHP中提问频率最高的11个面试题和答案
2014/09/02 PHP
phalcon框架使用指南
2016/02/23 PHP
PHP编程中尝试程序并发的几种方式总结
2016/03/21 PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
2017/03/13 PHP
js 判断 enter 事件
2009/02/12 Javascript
使用jQuery操作Cookies的实现代码
2011/10/09 Javascript
jQuery EasyUI API 中文文档 - PropertyGrid属性表格
2011/11/18 Javascript
利用jQuery简单实现产品展示图片左右滚动功能(示例代码)
2014/01/02 Javascript
jquery中的$(document).ready()使用小结
2014/02/14 Javascript
简易的投票系统以及js刷票思路和方法
2015/04/07 Javascript
JS定时检测任务任务完成后执行下一步的解决办法
2016/12/22 Javascript
AngularJS实现表单验证功能详解
2017/10/12 Javascript
JS实现的简单表单验证功能示例
2017/10/13 Javascript
详谈构造函数加括号与不加括号的区别
2017/10/26 Javascript
vue项目中的webpack-dev-sever配置方法
2017/12/14 Javascript
微信小程序实现收藏与取消收藏切换图片功能
2018/08/03 Javascript
微信小程序开发之tabbar图标和颜色的实现
2018/10/17 Javascript
JavaScript两种计时器的实例讲解
2019/01/31 Javascript
vue-cli的build的文件夹下没有dev-server.js文件配置mock数据的方法
2019/04/17 Javascript
浅谈vue 锚点指令v-anchor的使用
2019/11/13 Javascript
Vue SPA 初次进入加载动画实现代码
2019/11/14 Javascript
详解python发送各类邮件的主要方法
2016/12/22 Python
Python学习入门之区块链详解
2017/07/25 Python
Python 使用type来定义类的实现
2019/11/19 Python
美国内衣第一品牌:Hanes(恒适)
2016/07/29 全球购物
GafasWorld西班牙:购买太阳镜、眼镜和隐形眼镜
2019/09/08 全球购物
委托协议书范本
2014/04/22 职场文书
医学专业毕业生求职信
2014/06/20 职场文书
电焊工岗位工作职责
2014/07/09 职场文书
领导干部作风整顿个人剖析材料
2014/10/11 职场文书
父亲婚礼答谢词
2015/01/04 职场文书
《用字母表示数》教学反思
2016/02/17 职场文书
小学秋季运动会加油口号及加油稿
2019/08/19 职场文书
Android开发之底部导航栏的快速实现
2022/04/28 Java/Android