垃圾回收
Javascript 具有自动垃圾回收机制,会定期对那些不再使用的变量、对象所占用的内存进行释放,原理就是找到不再使用的变量,然后释放掉其占用的内存
JavaScript 中存在两种变量:局部变量和全局变量。全局变量的生命周期会持续要页面卸载;而局部变量声明在函数中,它的生命周期从函数执行开始,直到函数执行结束,在这个过程中,局部变量会在堆或栈中存储它们的值,当函数执行结束后,这些局部变量不再被使用,它们所占有的空间就会被释放。(执行上下文退出)
当局部变量被外部函数使用时,其中一种情况就是闭包,在函数执行结束后,函数外部的变量依然指向函数内部的局部变量,此时局部变量依然在被使用,所以不会回收
垃圾回收的方式
浏览器通常使用的垃圾回收方法有两种:标记清除,引用计数。
1)标记清除(执行上下文)
- 标记清除是浏览器常见的垃圾回收方式,当变量进入执行环境时,就标记这个变量“进入环境”,被标记为“进入环境”的变量是不能被回收的,因为他们正在被使用。当变量离开环境时,就会被标记为“离开环境”,被标记为“离开环境”的变量会被内存释放。
- 垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后。垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
2)引用计数
-
另外一种垃圾回收机制就是引用计数,这个用的 ,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减 1。当这个引用次数变为 0 时,说明这个变量已经没有价值,因此,在在机回收期下次再运行时,这个变量所占有的内存空间就会被释放出来。
-
这种方法会引起循环引用的问题:例如: obj1 和 obj2 通过属性进行相互引用,两个对象的引用次数都是 2。当使用循环计数时,由于函数执行完后,两个对象都离开作用域,函数执行结束,obj1 和 obj2 还将会继续存在,因此它们的引用次数永远不会是 0,就会引起循环引用。
obj1.a = null;
obj2.a = null;
GC
闭包似乎只能在新生代空闲区域做整理内存,但是不能被老生代给回收
被闭包引用的对象,先在新生代的对象区域和空闲区域的对象区域
作为活动对象从对象区域被复制到空闲区域
进行有序排列
然后倒会对象区域(晋升),但是为有序的对象(没有碎片)
两次整理后会进入老生代,被主垃圾回收器管理
老生代主要用标记清除,也会进行内存整理
.png)
.png)
