低层次的语言,如C,具有低级别的内存管理命令,如:malloc()和free(),需要开发者手工释放内存。然而像javascript这样的高级语言情况则不同,对象(objects, strings )等创建的时候分配内存,当他们不在使用的时候内存会被自动回收,这个自动回收的过程被称为垃圾回收。因为垃圾回收的存在,让javascript等高级 语言开发者产生了一个错误的认识,以为可以不用关心内存管理。下面就重新认识一下内存回收的机制:
一、内存生命周期
不管什么样的编程语言,内存的生命周期基本上是一致的: 分配你需要的内存 -> 使用他进行读写操作 -> 当内存不需要的时候,释放资源 。
步骤1和步骤2对于所有语言都一样,能明显觉察到。至于步骤3,低级别语言需要开发者显式执行。而对于像javascript这样的高级语言,这部分操作是交给解析器完成的,所以你不会觉察到。
二、JavaScript 中的内存泄漏
内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束。由于浏览器垃圾回收方法有bug,会产生内存泄露。
三、Javascript中出现内存泄露的主要原因是什么?
1)循环引用
一个很简单的例子:一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的Javascript对象,这个DOM对象可能 会引发内存泄露。这个DOM对象的引用将不会在脚本停止的时候被垃圾回收器 回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为 null。
2)Javascript闭包
因为Javascript范围的限制,许多实现依赖Javascript闭包。
闭包可以导致内存泄露是因为内部方法保持一个对外部方法变量的引用,所以尽管方法返回了内部方法还可以继续访问在外部方法中定义的私有变量。对Javascript程序员来说最好的做法是在页面重载前断开所有的事件处理器。
3)DOM插入顺序
当2个不同范围的 DOM 对象连添加到一起的时候一个临时的对象会被创建。这个DOM对象改变范围到document时,那个临时对象就没用了。也就是说, DOM 对象应该按照从当前页面存在的最上面的 DOM 元素开始往下直到剩下的 DOM 元素的顺序添加,这样它们就总是有同样的范围,不会产生临时对象。
4)如何检测?
内存泄露对开发者来说一般很难检测因为它们是由一些大量代码中的意外的错误引起的,但它在系统内存不足前并不影响程序的功能。这就是为什么会有人在很长时间的测试期中收集应用程序性能指标来测试性能。
最简单的检测内存泄露的方式是用任务管理器检查内存使用情况。在Chrome浏览器的新选项卡中打开应用并查看内存使用量是不是越来越多。还有其他的调试工具提供内存监视器,比如Chrome开发者工具。这是谷歌开者这网站中的堆分析的特性的教程。
四、jquery的缺点
优秀的jquery的一个缺点是比较容易污染Dom结构,从而导致了内存泄露。使用remove()和empty()方法能删除dom结构上的节点,删除的节点只是游离Dom的节点,以备再次恢复取回,但不能释放所占的内存空间。我遇到的问题是使用jquery实时插入<p>内容</p>,结果随着插入的次数增长,内存也在增长。最后改用原生js,就解决了。
参考:
http://www.jb51.net/article/32612.htm
http://www.php100.com/html/webkaifa/javascript/2012/0504/10356.html