Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4795674
  • 博文数量: 890
  • 博客积分: 17977
  • 博客等级: 上将
  • 技术积分: 8621
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-26 09:59
个人简介

一个好老好老的老程序员了。

文章分类

全部博文(890)

文章存档

2020年(7)

2019年(40)

2018年(88)

2017年(130)

2015年(5)

2014年(12)

2013年(41)

2012年(36)

2011年(272)

2010年(1)

2009年(53)

2008年(65)

2007年(47)

2006年(81)

2005年(12)

分类: Python/Ruby

2012-05-30 21:17:58

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

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

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

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

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

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

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

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

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

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

1:相互引用/循环引用

  1.   
  2.             function A()  
  3.             {  
  4.                 this.b;  
  5.             }  
  6.             function B()  
  7.             {  
  8.                 this.a;  
  9.             }  
  10.             var a=new A();  
  11.             var b=new B();  
  12.             a.b=b;  
  13.             b.a=a;  
  14.           
  15.           

这样的结果是什么,当然是a,b的技术永远也不会变成0。所以说,当我们不需要的时候,解引用。添加上下面两句。
  1. a.b=null;  
  2.             b.a=null;  
a.b=null; b.a=null;
我们这里只是举了两个对象,当三个甚至更多的时候,更要注意。

2:自引用

  1.   
  2.             function A()  
  3.             {  
  4.                 this.a;  
  5.             }  
  6.             var a=new A();  
  7.             a.a=a;  
  8.           
解决办法和上面的一样,解引用

3:事件绑定

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

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

4:闭包

  1. function leak(){  
  2.                var o = {};  
  3.                function closure(){  
  4.                }  
  5.                o.f = closure;  
  6.            }  
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/

阅读(2620) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~