JAVASCRIPT
的内存回收机制
- 以Google的
V8
引擎为例,在V8
引擎中所有的JAVASCRIPT
对象都是通过堆
来进行内存分配的。当我们在代码中声明变量
并赋值
时,V8
引擎就会在堆内存
中分配一部分给这个变量
。如果已申请的内存
不足以存储这个变量
时,V8
引擎就会继续申请内存
,直到堆
的大小达到了V8
引擎的内存上限为止(默认情况下,V8
引擎的堆内存
的大小上限在64位系统
中为1464MB
,在32位系统
中则为732MB
)。- 另外,
V8
引擎对堆内存
中的JAVASCRIPT
对象进行分代管理
。
- 新生代。
- 新生代即存活周期较短的
JAVASCRIPT
对象,如临时变量、字符串等- 老生代。
- 老生代则为经过多次垃圾回收仍然存活,存活周期较长的对象,如主控制器、服务器对象等。
- 垃圾回收算法。
- 垃圾回收算法一直是编程语言的研发中是否重要的一环,而
V8
引擎所使用的垃圾回收算法主要有以下几种。
Scavange
算法:通过复制的方式进行内存空间管理,主要用于新生代的内存空间;Mark-Sweep
算法和Mark-Compact
算法:通过标记来对堆内存进行整理和回收,主要用于老生代对象的检查和回收。对象进行回收。
引用
。
- 当函数执行完毕时,在函数内部所声明的对象
不一定
就会被销毁。引用(
Reference
)是JAVASCRIPT
编程中十分重要的一个机制。
是指
代码对对象的访问
这一抽象关系,它与C/C++
的指针有点相似,但并非同物。引用同时也是JAVASCRIPT
引擎在进行垃圾回收
中最关键的一个机制。var val = 'hello world'; function foo() { return function() { return val; }; } global.bar = foo();当代码执行完毕时,对象
val
和bar()
并没有被回收释放,JAVASCRIPT
代码中,每个变量
作为单独一行而不做任何操作,JAVASCRIPT
引擎都会认为这是对对象
的访问行为,存在了对对象的引用
。为了保证垃圾回收
的行为不影响程序逻辑的运行,JAVASCRIPT
引擎不会把正在使用的对象
进行回收。所以判断对象
是否正在使用中的标准,就是是否仍然存在对该对象
的引用
。JAVASCRIPT
的引用
是可以进行转移
的,那么就有可能出现某些引用被带到了全局作用域,但事实上在业务逻辑里已经不需要对其进行访问了,这个时候就应该被回收,但是JAVASCRIPT
引擎仍会认为程序仍然需要它。IE
下闭包引起跨页面内存泄露。
JAVASCRIPT
的内存泄露处理
给
DOM
对象添加的属性是一个对象的引用。var MyObject = {}; document.getElementByIdx_x('myDiv').myProp = MyObject;解决方法:在window.onunload事件中写上:
document.getElementByIdx_x('myDiv').myProp = null;DOM对象与JS对象相互引用。
function Encapsulator(element) { this.elementReference = element; element.myProp = this; } new Encapsulator(document.getElementByIdx_x('myDiv'));解决方法:在onunload事件中写上:
document.getElementByIdx_x('myDiv').myProp = null;给DOM对象用attachEvent绑定事件。
function doClick() {} element.attachEvent("onclick", doClick);解决方法:在onunload事件中写上:
element.detachEvent('onclick', doClick);从外到内执行appendChild。这时即使调用removeChild也无法释放。
var parentDiv = document.createElement_x("div"); var childDiv = document.createElement_x("div"); document.body.appendChild(parentDiv); parentDiv.appendChild(childDiv);解决方法:从内到外执行appendChild:
var parentDiv = document.createElement_x("div"); var childDiv = document.createElement_x("div"); parentDiv.appendChild(childDiv); document.body.appendChild(parentDiv);反复重写同一个属性会造成内存大量占用(但关闭IE后内存会被释放)。
for(i = 0; i < 5000; i++) { hostElement.text = "asdfasdfasdf"; }这种方式相当于定义了5000个属性,解决方法:无。
内存
不是缓存
。
- 不要轻易将
内存
当作缓存
使用。- 如果是很重要的资源,请不要直接放在
内存
中,或者制定过期机制
,自动销毁过期缓存
。CollectGarbage
。
CollectGarbage
是IE
的一个特有属性,用于释放内存的使用方法,将该变量或引用对象设置为null
或delete
然后在进行释放动作,在做CollectGarbage
前,要必需清楚的两个必备条件:(引用)。
- 一个对象在其生存的上下文环境之外,即会失效。
- 一个全局的对象在没有被执用(引用)的情况下,即会失效