详谈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 相关文章推荐
SlideView 图片滑动(扩展/收缩)展示效果
Aug 01 Javascript
xss文件页面内容读取(解决)
Nov 28 Javascript
js获取和设置属性的方法
Feb 20 Javascript
jQuery实现图片加载完成后改变图片大小的方法
Mar 29 Javascript
jQuery实现手机自定义弹出输入框
Jun 13 Javascript
node.js实现快速截图
Aug 27 Javascript
使用snowfall.jquery.js实现爱心满屏飞的效果
Jan 05 Javascript
jQuery选择器特殊字符与属性空格问题
Aug 14 jQuery
javascript 开发之网页兼容各种浏览器
Sep 28 Javascript
对vue 键盘回车事件的实例讲解
Aug 25 Javascript
mapboxgl实现带箭头轨迹线的代码
Jan 04 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数组函数知识汇总
2016/05/12 PHP
php5.3后静态绑定用法详解
2016/11/11 PHP
Yii2中简单的场景使用介绍
2017/06/02 PHP
浅谈PHP中的面向对象OOP中的魔术方法
2017/06/12 PHP
PHP7基于curl实现的上传图片功能
2018/05/11 PHP
用脚本调用样式的几种方法
2006/12/09 Javascript
jquery无缝向上滚动实现代码
2013/03/29 Javascript
jQuery之日期选择器的深入解析
2013/06/19 Javascript
JS+CSS实现Li列表隔行换色效果的方法
2015/02/16 Javascript
JavaScript常用函数工具集:lao-utils
2016/03/01 Javascript
AngularJS中watch监听用法分析
2016/11/04 Javascript
Bootstrap源码解读下拉菜单(4)
2016/12/23 Javascript
JS在浏览器中解析Base64编码图像
2017/02/09 Javascript
原生js实现可拖拽效果
2017/02/28 Javascript
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
2018/08/24 Javascript
如何优雅地在vue中添加权限控制示例详解
2019/03/07 Javascript
vuejs element table 表格添加行,修改,单独删除行,批量删除行操作
2020/07/18 Javascript
Python使用pygame模块编写俄罗斯方块游戏的代码实例
2015/12/08 Python
Python中__slots__属性介绍与基本使用方法
2018/09/05 Python
Windows下python3安装tkinter的问题及解决方法
2020/01/06 Python
日本最新流行服饰网购:Nissen
2016/07/24 全球购物
微软澳洲官方网站:Microsoft Australia
2017/01/10 全球购物
哄娃神器4moms商店:美国婴童用品品牌
2019/03/07 全球购物
Lentiamo比利时:便宜的隐形眼镜
2020/02/14 全球购物
工商管理专业实习大学生自我鉴定
2013/09/19 职场文书
会计电算化应届生求职信
2013/11/03 职场文书
教师试用期自我鉴定
2014/02/12 职场文书
《英英学古诗》教学反思
2014/04/11 职场文书
2014年网络管理员工作总结
2014/12/01 职场文书
学生安全责任协议书
2016/03/22 职场文书
生鲜超市—未来中国最具有潜力零售业态
2019/08/02 职场文书
2019朋友新婚祝福语精选
2019/10/10 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python
Golang实现AES对称加密的过程详解
2021/05/20 Golang
MYSQL如何查看进程和kill进程
2022/03/13 MySQL
Mysql多层子查询示例代码(收藏夹案例)
2022/03/31 MySQL