JS垃圾回收机制
js中,垃圾回收机制,是一种自动管理内存的机制。找到不在需要的变量,并释放他的内存。
1、为什么会有垃圾回收机制。
因为每次创建一个变量/函数都会占用内存,如果不清理内存都会导致内存泄漏。
内存泄露
程序去申请内存,无法释放已申请的空间,一块内存没办法使用,也没办法释放。
常见的内存泄露
- 全局变量
全局变量会导致内存无法回收,会造成内存泄露。平时开发的时候建议少使用全局变量,来控制内存。
- 定时器
定时器不清除也会导致内存无法回收,造成内存泄露
内存溢出
大量的内存泄露会导致内存溢出
2、垃圾回收在什么时候执行。
1、浏览器中会定时调用垃圾回收机制来清理全局执行上下文中标记为0或者值为undefined,null的变量(计数清除)。
2、当函数执行完毕后会清除所有被标记为离开环境的内容。
3、垃圾回收机制执行的原理
1、计数引用:当值被引用,那么他的引用次数就会加1.
var arr = [1,2,3]
如上这个数组的引用次数就为1,再次引用就会依次叠加。
var arr = null
这是引用次数就为0,他就会被垃圾回收机制清除。
- 2、标记清除:当全局执行上下文把权限下放到函数执行上下文时,会函数中的值进行标记(进入环境)。当函数执行完毕后执行上下文返还到全局的时候就会标记为(离开环境)所有有离开环境的值都会被清除。
function fn () {
var a = 10 //标记‘进入环境’
var b = 'hollen word' //标记‘进入环境’
}
fn() //执行完毕后a b被标记为离开环境 垃圾回收机制清除内存。
但是不会清理在执行环境变量中被执行中的环境调用的变量(闭包)
WeakSet、WeakMap
这两种类型他们不会被计入垃圾回收机制。
var a = new WeakMap()
var b = new Object()
a.set(b,'holle word') //这里的b不会计入,也就是说new Object的计数值为1 而不是二。
b = null //这时计数为0
a.get(b) //找不到undefined 因为垃圾回收机制清理了内存,b也就消失了
补充
引用计数:navigitor 3.0是最早使用引用计数策略的浏览器,但很快就遇到了一些问题,就是循环引用导致计数的值永远不为0并且多次循环导致大量的内存无法回收。在4.0的时候就废弃了,开始使用标记清除来实现。但访问COM对象一九依然使用引用技术来实现。存储一些问题,比如说下面这种情况。
var a = 1;
var b = 2;
console.log(a,b)
这里我们可以看到a 和 b,按照引用技术的方法,a和b的引用次数都是1,永远都不可能会是0,所以她永远都不会清楚。
性能:
垃圾回收机制是周期性运行的, IE6中就是是固定临界值的256个变量、4098个对象(数组、字面量、数据元素)或者64kb的字符串,达到上面一个临界值。就会触发垃圾回收机制。但有一个问题就是一个脚本本身就达到了这些条件那么垃圾回收机制就会一直触发。
ie7中做了优化,变为了动态临界值。如果垃圾回收机制回收的内存分配量低于15%,临界值就会加倍,若大于85%的内存分配量就会重新变为原始值。