js垃圾回收机制
所有全局变量以及全局声明的Array,promise,Object都在内存当中都不是垃圾,因为可能在某一处会用到,如果一个变量没有可能会用到,那就是垃圾
一个局部函数里的变量在调用以后就变成了垃圾,但是在函数调用的时候 因为全局函数引用了 b 所以此时var b 不是一个垃圾
var a=1
function fn (){
var b=2
}
fn()
console.log(a)
怎样认定是不是一个内存垃圾,如何收集垃圾
当一个对象或者变量没有被引用即可认定为是个垃圾,当然还有一种特殊情况就是引用之间形成闭环也是一种垃圾。 全局声明一个family对象,family对象引用着father和mother对象,mother和father对象也互相引用着,此时将window.family置空,那么就形成了一个闭环
垃圾算法
1.标记-清除-算法mark-swipe算法(整个被浏览一遍) 从全局global遍历看看全局变量或者对象对引用了谁,然后再将这个对象二次遍历一遍,直到没有引用为止,引用的都给一个标记。 缺点是标记起来很慢,假如全局对象有10000个呢 每次都要遍历一边吗? 解决方法 1.将对象分为old和new (generation collection ) 新生代的对象 比如说立即执行函数里面的局部变量,会被例课销毁 old 比方说window对象 他在内存中停留了很久,基本上不会删除(推测) 可以把这种策略归为old代(这是一种策略,当然不一定按照这个) 3s遍历一次 new 执行函数里的 局变量 马上标记马上删除 5ms一次
2.10000个对象分批收集垃圾,每次拟定1000 增量收集 3.空闲时间收集,当js闲下来的时候再执行
面试答题
解释什么是垃圾
没有被引用就是垃圾,还有一种特殊情况就是 三者之间互想被引用,但是没有被其他全局的对象引用到,形成一个闭环也是垃圾
浏览器是如何找到垃圾并把它们删除的? 使用了标记清除算法
从全局对象开始遍历,看看引用了什么,引用到了就标记一下,没有标记的就清除 前端又有特殊的地方,dom和js进程。
<div class="a">xxx</div>
var a=document.querySelector('.a')
a.onclick=function(){
}
settimeout(function(){
a.remove()
// remove只是再节点中删除,但还是存在内存中。如果是a=null呢 会不会在内存中删除?不会因为页面上还是存在一个div,dom,还是存在的/此时的a只是一个变量div,dom元素引用了这个函数
a=null
// ie有bug 如果dom中没有,但是此dom引用了一个click 会被认为还是存在的
// a.onclick=null ie
},3000)
引用计数算法
全局对象为1,被引用一次就加1 ,如果为0,那就删除 优点没有必要沿着根集合开始遍历,即刻回收垃圾
参考文章