详谈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 相关文章推荐
[原创]js获取数组任意个不重复的随机数组元素
Mar 15 Javascript
js删除所有的cookie的代码
Nov 25 Javascript
关于URL中的特殊符号使用介绍
Nov 03 Javascript
Js获取下拉框选定项的值和文本的实现代码
Feb 26 Javascript
jQuery+css实现的切换图片功能代码
Jan 27 Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
Apr 26 jQuery
React Native中的RefreshContorl下拉刷新使用
Oct 09 Javascript
vue-cli启动本地服务局域网不能访问的原因分析
Jan 22 Javascript
vue几个常用跨域处理方式介绍
Feb 07 Javascript
Node.js使用MySQL连接池的方法实例
Feb 11 Javascript
VUE中使用MUI方法
Feb 12 Javascript
微信自定义分享链接信息(标题,图片和内容)实现过程详解
Sep 04 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里得到前天和昨天的日期的代码
2007/08/16 PHP
php小型企业库存管理系统的设计与实现代码
2011/05/16 PHP
php连接mssql数据库的几种方法
2013/02/21 PHP
PHP定时执行任务实现方法详解(Timer)
2015/07/30 PHP
PHP实现读取文件夹及批量重命名文件操作示例
2019/04/15 PHP
PHP 范围解析操作符(::)用法分析【访问静态成员和类常量】
2020/04/14 PHP
JS宝典学习笔记(下)
2007/01/10 Javascript
jQuery获取CSS样式中的颜色值的问题,不同浏览器格式不同的解决办法
2013/05/13 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
QQ空间顶部折页撕开效果示例代码
2014/06/15 Javascript
JS实现鼠标经过好友列表中的好友头像时显示资料卡的效果
2014/07/02 Javascript
jQuery 实现自动填充邮箱功能(带下拉提示)
2014/10/14 Javascript
javascript进行四舍五入方法汇总
2014/12/16 Javascript
angularJS中router的使用指南
2015/02/09 Javascript
Vue.js每天必学之指令系统与自定义指令
2016/09/07 Javascript
Javascript实现基本运算器
2017/07/15 Javascript
前端开发不得不知的10个最佳ES6特性
2017/08/30 Javascript
使用ng-packagr打包Angular的方法示例
2018/09/21 Javascript
从源码里了解vue中的nextTick的使用
2018/11/22 Javascript
JS工厂模式开发实践案例分析
2019/10/17 Javascript
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
2016/05/17 Python
python中import reload __import__的区别详解
2017/10/16 Python
python 实现字符串下标的输出功能
2020/02/13 Python
简单的Python人脸识别系统
2020/07/14 Python
python如何快速拼接字符串
2020/10/28 Python
python 实现一个图形界面的汇率计算器
2020/11/09 Python
python进行二次方程式计算的实例讲解
2020/12/06 Python
html2canvas把div保存图片高清图的方法示例
2018/03/05 HTML / CSS
希尔顿酒店官方网站:Hilton Hotels
2017/06/01 全球购物
英国户外装备商店:Ultimate Outdoors
2019/05/07 全球购物
预备党员思想汇报范文
2013/12/29 职场文书
索桥的故事教学反思
2014/02/06 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
新郎婚礼答谢词
2015/01/04 职场文书
2016领导干部廉洁自律心得体会
2016/01/13 职场文书
MySQL pt-slave-restart工具的使用简介
2021/04/07 MySQL