JavaScript垃圾回收机制

kdown>

操作系统的三种内存分配机制

静态分配
从静态存储区域分配内存。程序编译的时候内存已经分配好了,并且在程序的整个运行期间都存在,如静态变量和全局变量。
自动分配
在栈中为局部变量分配内存的方法,栈中的内存可以随着代码块退出时的出栈操作被自动释放。例如在执行函数时,函数内局部变量的存储单元可以在栈上创建,函数结束时这些存储单元自动被释放。
动态分配
从静态存储区域分配内存。程序编译的时候内存已经分配好了,并且在程序的整个运行期间都存在,如静态变量和全局变量。
栈在底堆在上,function的执行都是通过入栈出栈,执行的时候去堆取到数据推入执行栈,成员变量在堆,局部变量在栈,全局变量也在堆;引用类型的引用变量存储在栈中,指向于实际存储在堆中的实际对象。

标记清楚

JavaScript最常用的垃圾回收方式是标记清楚,标记清楚是最早ie游览器采用的方式,现代游览器基本全部使用标记清楚的垃圾回收策略。
标记清楚:当变量进入执行环境(在函数里声明,赋值等),变量被标记为进入环境,进入环境的变量的内存永远不会释放,当变量离开环境(执行完函数)时,标记为“离开环境”,将其内存回收。

引用计数

引用计数在JavaScript内存回收中用的较少,现在只有KDE下的KJS引擎的游览器在采用,而最早是网景3游览器采用了这种方式。
引用计数的含义是跟踪记录每个值被引用的次数,当声明一个变量并将一个引用类型赋值给变量时,引用次数是1.如果值又赋给另外一个变量,引用次数加1,如果包含这个值引用的变量取得了其他值,引用次数减1,当引用次数为0,表示不能再访问到,即可回收。
值得注意的是,虽然基本没有游览器上JavaScript使用引用计数了,但ie9一下游览器很多对象不是原生JavaScript对象,比如DOM与BOM中的对象就是c++以COM(组件对象模型)实现的,而COM的垃圾回收采用的是引用计数策略,因此即使游览器采用标记清楚实现垃圾回收,但只要在游览器设计COM对象,就使用了引用计数。这会引起循环引用的问题。如;

var ele = document.getElementById('ele');
var myObj = new Object();
myObj.ele = ele;  //新对象一个属性引用了com对象
ele.someObj = myObj;  ///com对象一个属性引用了JavaScript对象

在上述情况下,即使将DOM从页面移除,其内存也不会被回收。为了避免出现,要在使用完毕后手工回收,赋值null来手工解除引用。
ie9以上的游览器上,BOM与DOM变成了JavaScript对象,不会再出现这个问题,但做兼容性处理的时候这种内存泄漏是要考虑的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

😉😐😡😈🙂😯🙁🙄😛😳😮:mrgreen:😆💡😀👿😥😎😕