JavaScript 垃圾回收

前情提要

面试中老是会遇到 JavaScript 垃圾回收的问题,特地上网查了一下,终于找到一个描述的比较详细的了, 在这里与你们 分享一下,本身也作一个备份,以便随时查看面试

JavaScript 垃圾回收

垃圾回收是一种自动的 内存管理 机制算法

当一个电脑上的动态内存不在须要时,就应该予以释放,以让出内存,这种内存资源管理,成为垃圾回收函数

  • JavaScript 中的内存管理是自动执行的,并且是不可见的。优化

  • 建立基本类型、对象、函数... 全部这些都是须要内存。spa

  • 当再也不须要某样东西时会发生什么?JavaScript 引擎是如何发现并清理它?code

可达性

  • JavaScript 中内存管理的主要概念是可达性
  • “可达性” 值就是那些以某种方式可访问或可用的值,它们被保存在内存中

可达值

  • 有一组基本的固有可达值,因为显而易见的缘由没法删除,这些值称为根
    • 本地函数的局部变量和参数
    • 当前嵌套调用链上的其余函数的变量和参数
    • 全局变量
    • 还有一些其余的,内部的
  • 若是引用或引用链能够从根访问任何其余值,则认为该值是可访问的
    • 若是局部变量中有对象,而且该对象具备引用另外一个对象的属性,则该对象被视为可达性,它引用的那些也是能够访问的

JavaScript 引擎中有一个后台进程称为垃圾回收器,它监视全部对象,并删除那些不可访问的对象

案例

// user 具备对象的引用
let user = {
    name: 'John'
}
// 全局变量“user”引用对象 {name:“John”}
// John 的 “name” 属性存储一个基本类型,所以它被绘制在对象中

// user 的值被覆盖,则引用丢失
user = null
// 如今 John 变成不可达的状态,没有办法访问它,没有对它的引用。垃圾回收器将丢弃 John 数据并释放内存
复制代码

两个引用 —— 将引用从 user 复制到 admin

// user 具备对象的引用
let user = {
    name: 'John'
}
let admin = user

user = null
// 该队爱那个让然能够经过 admin 全局访问变量,因此它在内存中
admin = null
// user 和 admin 都被 null 覆盖,那么它能够被释放
复制代码

相互关联的对象

function marry (man, woman) {
    woman.husband = man
    man.wife = woman
    return {
        father: man,
        mother: woman
    }
}
let family = marry({
    name: 'John'
}, {
    name: 'Ann'
})
// 函数 marry 经过给两个对象彼此提供引用来“联姻”它们,并返回一个包含两个对象的新对象.
// 目前为止,全部对象都是可访问的

// 删除两个引用
delete family.father
delete family.mother.husband
// 仅仅删除这两个引用中的一个是不够的,由于全部对象仍然是可访问的
// 把这两个都删除,就能够看到 John 不在有传入的引用
// 该对象引入其余对象可有可无
// 该对象被引入,才会作可达性分析
// 所以,John 如今是不可访问的,并将从内存中删除全部不可访问的数据
复制代码

没法访问的数据块

有可能整个相互链接的对象变得不可访问并从内存中删除对象

// 源对象同上
// 而后 =>
family = null
// John 和 Ann 仍然链接在一块儿,都有传入的引用
// 但 "family" 对象已经从根上断开了连接,再也不有对它的引用,所以下面的整个块变得不可到达,并将被删除
复制代码

内部算法

基本的垃圾回收算法称为 “标记-清除” ,按期执行如下“垃圾回收”步骤:进程

  • 垃圾回收器获取根并 “标记" (记住) 他们
  • 而后它访问并 “标记” 全部来自它们的引用
  • 而后它访问标记的对象并标记它们的引用。全部被访问的对象都被记住,以便之后再也不访问同一个对象两次
  • 以此类推,直到有未访问的引用(能够从根访问)为止
  • 除标记的对象外,全部对象都被删除

垃圾收集的工做原理

  • 第一步标记
  • 而后标记 它们的引用 以及 子孙代的引用
  • 进程中 不能访问的对象 被认为是 不可访问的 ,将被 删除

JavaScript 引擎应用了许多优化,使其运行得更快,而且不影响执行

优化 =>ip

  • 分代回收内存

    • 对象分为两组:“新对象”“旧对象”
    • 许多对象出现,完成它们的工做并迅速结束,它们很快就会被清理干净
    • 那些活的足够久的对象,会变”老“,而且不多接受检查
  • 增量回收

    • 若是有不少对象,而且咱们试图一次遍历并标记整个对象集,那么可能会花费一些时间,并在执行中会有必定的延迟
    • 所以,引擎试图将垃圾回收分解为多个部分
    • 而后,各个部分分别执行
    • 这须要额外的标记来跟踪变化,这样有不少微小的延迟,而不是很大的延迟
  • 空闲时间回收

    • 垃圾回收器只在 CPU 空闲时运行,以减小对执行的可能影响

面试

  • 什么是垃圾?
    • 通常来讲没有被引用的对象就是垃圾,就是要被清除
    • 若是几个对象引用造成一个环,互相引用,但根访问不到它们,这几个对象也是垃圾,也要被清除
  • 如何检测垃圾?
    • 一种算法是标记 标记-清除 算法
相关文章
相关标签/搜索