详谈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 相关文章推荐
jquerymobile checkbox及时刷新才能获取其准确值
Apr 14 Javascript
JavaScript如何从listbox里同时删除多个项目
Oct 12 Javascript
$.each遍历对象、数组的属性值并进行处理
Jul 18 Javascript
JS实现在线统计一个页面内鼠标点击次数的方法
Feb 28 Javascript
JQuery控制图片由中心点逐渐放大效果
Jun 26 Javascript
浅谈Javascript中的函数、this以及原型
Oct 09 Javascript
jQuery动态添加与删除tr行实例代码
Oct 18 Javascript
vue2.0s中eventBus实现兄弟组件通信的示例代码
Oct 25 Javascript
vue拖拽组件使用方法详解
Dec 01 Javascript
js中数组对象去重的两种方法
Jan 18 Javascript
JS Math对象与Math方法实例小结
Jul 05 Javascript
详解在vue-cli3.0中自定css、js和图片的打包路径
Aug 26 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函数分享之curl方式取得数据、模拟登陆、POST数据
2014/06/04 PHP
分享微信扫码支付开发遇到问题及解决方案-附Ecshop微信支付插件
2015/08/23 PHP
PHP新建类问题分析及解决思路
2015/11/19 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
2015/12/19 PHP
Laravel框架控制器的request与response用法示例
2019/09/30 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
JavaScript 继承详解(一)
2009/07/13 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
Extjs表单常见验证小结
2014/03/07 Javascript
详谈nodejs异步编程
2014/12/04 NodeJs
JavaScript中定义函数的三种方法
2015/03/12 Javascript
js获取当前年月日-YYYYmmDD格式的实现代码
2016/06/01 Javascript
AngularJS入门教程之Select(选择框)详解
2016/07/27 Javascript
浅析jQuery操作select控件的取值和设值
2016/12/07 Javascript
React中使用collections时key的重要性详解
2017/08/07 Javascript
前端开发不得不知的10个最佳ES6特性
2017/08/30 Javascript
Vue2.0基于vue-cli+webpack Vuex的用法(实例讲解)
2017/09/15 Javascript
通过源码分析Vue的双向数据绑定详解
2017/09/24 Javascript
vue 自定义全局方法,在组件里面的使用介绍
2018/02/28 Javascript
使用C#配合ArcGIS Engine进行地理信息系统开发
2016/02/19 Python
Python cookbook(字符串与文本)在字符串的开头或结尾处进行文本匹配操作
2018/04/20 Python
教你利用Python玩转histogram直方图的五种方法
2018/07/30 Python
简单了解Python变量作用域正确使用方法
2020/06/12 Python
Expedia英国:全球最大的在线旅游公司
2017/09/07 全球购物
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
澳大利亚波希米亚风时尚品牌:Tree of Life
2019/09/15 全球购物
什么是虚拟内存?虚拟内存有什么优势?
2016/02/09 面试题
资产经营总监岗位职责范文
2013/12/01 职场文书
孝老爱亲模范事迹材料
2014/05/25 职场文书
圣诞晚会主持词
2015/07/01 职场文书
运动会班级前导词
2015/07/20 职场文书
感恩的心主题班会
2015/08/12 职场文书
2016大一新生入学教育心得体会
2016/01/23 职场文书
管理者日常工作必备:22条企业管理流程模板!
2019/07/12 职场文书
IDEA使用SpringAssistant插件创建SpringCloud项目
2021/06/23 Java/Android
详解jQuery的核心函数和事件处理
2022/02/18 jQuery