详谈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函数
Aug 01 Javascript
JavaScript中的Document文档对象
Jan 16 Javascript
很酷的javascript loading效果代码
Jun 18 Javascript
jQuery版Tab标签切换
Mar 16 Javascript
jquery中的ajax方法怎样通过JSONP进行远程调用
May 04 Javascript
js中split和replace的用法实例
Feb 28 Javascript
ES6概念 Symbol toString()方法
Dec 25 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
Jun 14 Javascript
VsCode插件整理(小结)
Sep 14 Javascript
微信小程序导航栏滑动定位功能示例(实现CSS3的positionsticky效果)
Jan 24 Javascript
深入了解query和params的使用区别
Jun 24 Javascript
详解Vue的异步更新实现原理
Dec 22 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 注释规范
2012/03/29 PHP
解析php addslashes()与addclashes()函数的区别和比较
2013/06/24 PHP
php类中的各种拦截器用法分析
2014/11/03 PHP
PHP类型约束用法示例
2016/09/28 PHP
PHP+MySQL实现模糊查询员工信息功能示例
2018/06/01 PHP
小程序微信支付功能配置方法示例详解【基于thinkPHP】
2019/05/05 PHP
ajax更新数据后,jquery、jq失效问题
2011/03/16 Javascript
jquery 实现表单验证功能代码(简洁)
2012/07/03 Javascript
js实时获取系统当前时间实例代码
2013/06/28 Javascript
js 点击页面其他地方关闭弹出层(示例代码)
2013/12/24 Javascript
jQuery多级弹出菜单插件ZoneMenu
2014/12/18 Javascript
javascript设计模式之中介者模式Mediator
2014/12/30 Javascript
jquery文档操作wrap()方法实例简述
2015/01/10 Javascript
jQuery实现下拉加载功能实例代码
2016/04/01 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
浅谈Angularjs link和compile的使用区别
2016/10/21 Javascript
JS数字千分位格式化实现方法总结
2016/12/16 Javascript
Angular企业级开发——MVC之控制器详解
2017/02/20 Javascript
基于casperjs和resemble.js实现一个像素对比服务详解
2018/01/10 Javascript
JS执行控制之节流模式实例分析
2018/12/21 Javascript
JS实现的贪吃蛇游戏案例详解
2019/05/01 Javascript
了解JavaScript中let语句
2019/05/30 Javascript
微信小程序接入腾讯云验证码的方法步骤
2020/01/07 Javascript
JS实现网页烟花动画效果
2020/03/10 Javascript
Python中的yield浅析
2014/06/16 Python
python判断字符串是否纯数字的方法
2014/11/19 Python
python修改字典内key对应值的方法
2015/07/11 Python
Python内置函数—vars的具体使用方法
2017/12/04 Python
使用Pyinstaller转换.py文件为.exe可执行程序过程详解
2019/08/06 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
Python如何创建装饰器时保留函数元信息
2020/08/07 Python
python 基于pygame实现俄罗斯方块
2021/03/02 Python
FC-Moto美国:欧洲最大的摩托车服装和头盔商店之一
2019/08/24 全球购物
介绍一下Prototype的$()函数,$F()函数,$A()函数都是什么作用?
2014/03/05 面试题
给校长的建议书600字
2014/05/15 职场文书
Python Matplotlib绘制等高线图与渐变色扇形图
2022/04/14 Python