现在的位置: 首页 > 综合 > 正文

JavaScript垃圾回收与内存泄露

2013年12月05日 ⁄ 综合 ⁄ 共 1377字 ⁄ 字号 评论关闭

内存泄露是一个非常重要的一个问题,特别是对于JavaScipt,如果占用内存过大,将使整个浏览器的速度拖慢,造成一个很不好的用户体验。

内存泄露造成的原因在于没有及时的进行垃圾回收,或者只要页面存在,就不会进行垃圾回收。例如全局变量等等。

首先了解一下,关于垃圾回收机制,分为两种,标记清除法和引用计数法。

标记清除法,一个函数局部作用域,当这个函数调用的时候,内部定义的局部变量将进入运行环境。当函数调用完毕之后,这个变量就会被标记,当下一次垃圾清除的时候,一起删除。

引用计数法引用计数的含义是跟踪记录每个值被引用的次数。当声明一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数便是1,如果同一个值又被赋给另 一个变量,则该值的引用次数加1,相反,如果包含对这个值引用的变量又取得了另一个值,则这个值的引用次数减1。当这个值的引用次数为0时,说明没有办法
访问到它了,因而可以将其占用的内存空间回收。(JavaScript 高级程序设计第二版)。当退出作用域的时候,然后减1;

然后我们来看一下,内存分配方式。

静态分配:全局变量,函数之类的分配方式,由于他们页面没有关闭之前,他们是不会被清除的。

自动分配:局部变量,但不是所有局部变量,比如说自带的类型,只要不是动态分配的局部变量就是自动分配的。满足两个条件,

动态分配:使用new创建出来的,主动要求给分配空间的。

我们谈一下,内存泄露常见的一些地方吧,基本上都是引用计数法搞的。

1:相互引用/循环引用

<script defer>
        	function A()
			{
				this.b;
			}
			function B()
			{
				this.a;
			}
			var a=new A();
			var b=new B();
			a.b=b;
			b.a=a;
        
        </script>

这样的结果是什么,当然是a,b的技术永远也不会变成0。所以说,当我们不需要的时候,解引用。添加上下面两句。

a.b=null;
			b.a=null;

我们这里只是举了两个对象,当三个甚至更多的时候,更要注意。

2:自引用

<script >
        	function A()
			{
				this.a;
			}
			var a=new A();
			a.a=a;
        </script>

解决办法和上面的一样,解引用

3:事件绑定

一般来说,事件绑定是没有多少问题的。但是问题在于,如果你把这个DOM移除了,但是之前的事件监听仍然还在内存之中,之后就无法消除这个泄露问题了。

解决办法,就是在DOM移除之前就需要把这个事件绑定给移除掉。

4:闭包

 function leak(){
                var o = {};
                function closure(){
                }
                o.f = closure;
            }

我们从上面图上可以看出来,leak里面引用这o,而o.f引用closure,closure的环境位于leak,这就变成一个相互引用。对于这个东西来说,就要把函数放到外面来。

总体来说,如果减少内存泄露的话,就尽量减少相互引用,没有用的时候解引用,不要一直占据这内存。

并不是你关闭了这个页面或者页面跳转,内存泄露就不存在了,除非你关闭了整个浏览器

下面有两个小工具,用来检测内存泄露问题

SIEve http://ishare.iask.sina.com.cn/f/17304467.html

Leak Monitor https://addons.mozilla.org/zh-CN/firefox/addon/leak-monitor/

抱歉!评论已关闭.