一.什么是垃圾回收机制?
1.垃圾回收机制
垃圾回收机制(Garbage Collection) 简称 GC
JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。
正因为垃圾回收器的存在,许多人认为JS不用太关心内存管理的问题。
但如果不了解JS的内存管理机制,我们同样非常容易成内存泄漏(内存无法被回收)的情况。
不再用到的内存,没有及时释放, 就叫做 内存泄漏。
2.可达性
JavaScript 中主要的内存管理概念是 可达性。“可达”值是那些以某种方式可访问或可用的值。它们被存储在内存中。
1.这里列出固有的可达值的基本集合,这些值被称作 根(roots),并且明显不能被释放。
- 当前执行的函数,它的局部变量和参数。
- 当前嵌套调用链上的其他函数、它们的局部变量和参数。
- 全局变量。
- (还有一些其他的,内部实现)
2.如果一个值可以从根通过引用或者引用链进行访问,则认为该值是可达的。
例如,如果全局变量中有一个对象,并且该对象有一个属性引用了另一个对象,则 该 对象被认为是可达的。而且它引用的内容也是可达的。
在 JavaScript 引擎中有一个被称作 垃圾回收器 的东西在后台执行。它监控着所有对象的状态,并删除掉那些已经不可达的。
二.内存的生命周期
JS环境中分配的内存, 一般有如下生命周期:
- 内存分配 :当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
- 内存使用 :即读写内存,也就是使用变量、函数等
- 内存回收 :使用完毕,由垃圾回收自动回收不再使用的内存
- 说明:全局变量一般不会回收(关闭页面回收); 一般情况下局部变量的值不用了, 会被自动回收
拓展-JS垃圾回收机制-算法说明
堆栈空间分配区别:
- 栈 (操作系统) : 由 操作系统自动分配释放 函数的参数值、局部变量等,基本数据类型放到栈里面
- 堆 (操作系统) : 一般 由程序员分配释放 ,若程序员不释放,由 垃圾回收机制 回收。 复杂数据类型 放到堆里面
两种常见的浏览器 垃圾回收算法 : 引用计数法 和 标记清除法
● 引用计数
IE采用的引用计数算法, 定义“ 内存不再使用 ”,就是看一个 对象 是否有指向它的引用,没有引用了就回收对象。
算法:
- 跟踪记录被 引用的次数
- 如果被引用了一次,那么就记录次数1,多次引用会 累加 ++
- 如果减少一个引用就 减1 --
- 如果引用次数是 0 ,则释放内存
但它却存在一个致命的问题: 嵌套引用 (循环引用)
如果两个对象 相互引用 ,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄露。
因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露
● 标记清除法
现代的浏览器已经不再使用引用计数算法了。
现代浏览器通用的大多是基于 标记清除算法 的某些改进算法,总体思想都是一致的。
核心:
- 标记清除算法将“不再使用的对象”定义为“ 无法达到的对象 ”。
- 就是从 根部 (在JS中就是全局对象)出发定时扫描内存中的对象。 凡是能从 根部到达 的对象,都是还 需要使用 的。
- 那些 无法 由根部出发触及到的 对象被标记 为不再使用,稍后进行 回收 。
对于上面的例子,根部已经访问不到,所以自动清除