JS的垃圾回收机制【一篇读懂】,最新前端高级面试题汇

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

垃圾回收机制(GC:Garbage Collection):执行环境负责管理代码执行过程中使用的内存。JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,没有被释放,导致该内存无法被使用,垃圾回收机制(GC)会定期(周期性)找出那些不再继续使用的变量,然后释放其内存。

内存管理

  1. 内存:由可读写单元组成,表示一片可操作空间

  2. 管理:人为的去操作一片空间的申请,使用和释放

  3. 内存管理:开发者主动申请空间,使用空间,释放空间

  4. 管理流程:申请————使用————释放

1.JavaScript中的内存管理

分为下面三个步骤

申请内存空间

使用内存空间

释放内存空间

// 申请
let obj = {} 
// 使用 
obj.name = 'lg' 
// 释放 
js中没有释放api,我们这里就把它设置为null 
obj = null

2.JavaScript中的垃圾回收

概念

对我们前端而言JS的内存管理是自动的,每次我们创建一个对象、数组、函数的时候会自动分配一个内存空间。

那么什么是垃圾呢?

对象不再被引用的时候就是垃圾

对象不能从根上访问到的时候也是垃圾。

知道什么是垃圾之后,JS引擎就会出来工作,把它们占据的对象空间进行回收,这就叫做JS的垃圾回收。

下面我们引入一个概念,叫可达对象

可达对象

可以访问到的对象就是可达对象(引用、作用域链)

可达的标准就是从根出发是否能够被找到

JavaScript中的根就可以理解为是全局变量对象

可达样例

//可达对象

//我们定义了一个函数去接收两个变量obj1,obj2,互相指引

function objGroup(obj1,obj2) {

        obj1.next = obj2

        obj2.prev = obj1

        return {

             o1:obj1,

             o2:obj2

        }

}

let obj = objGroup({name:'obj1'},{name:'obj2'})

console.log(obj)

说明:

首先从全局的根出发,我们能找到一个可达的对象obj,它是通过一个函数调用之后,指向了一个内存空间(里面就是o1和o2),又通过相应的属性指向obj1和obj2的空间,这两个空间之间通过next和prev互相指向。

所以在这个例子里面,我们能从根访问到任何一个内存空间。

然后我们删除掉两行代码之后

function objGroup(obj1,obj2) {
    obj1.next = obj2
    //obj2.prev = obj1
    return {
        //o1:obj1,
        o2:obj2
    }
}
let obj = objGroup({name:'obj1'},{name:'obj2'})
console.log(obj)

这之后,我们所有能够找到obj1的线条都被删除了,于是obj1空间就会被认为是垃圾,js引擎就会找到它把它删除。

3.GC算法****介绍

GC****定义与作用

GC就是垃圾回收机制的简写

GC可以找到内存中的垃圾、并释放和回收空间。

GC算法是什么

GC是一种机制,垃圾回收器完成具体的工作

工作的内容就是查找垃圾释放空间、回收空间

算法就是工作时查找和挥手所遵循的规则

常见GC算法

引用计数:通过一个数字判断当前的是不是垃圾

标记清除:进行工作的时候给到活动对象添加一个标记,判断是否垃圾

标记整理:和标记清除类似,回收过程中做的事情不太一样

分代回收:不同生命周期的对象可以采取不同的收集方式,以便提高回收效率

引用计数:

  • 这种方式常常会引起内存泄漏,低版本的IE使用这种方式。机制就是跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个时该值的引用次数便减一。当该值引用次数为0时,则说明没有办法再访问这个值了,被视为准备回收的对象,每当过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。

a的引用次数

function f1(){
    var a ={}//a的引用次数0
    var b=a//a的引用次数1
    var c=a //a的引用次数2
    var b={}//a的引用次数1
    var c=[]//a的引用次数0
}

引用计数优点:

  • 发现垃圾时立即回收
  • 最大限度减少程序暂停(当内存快满的时候就立刻去找引用计数为0的删掉)

引用计数的缺点:

  • 造成比较大的性能开销
  • 造成循环引用的问题

//对象之间的循环引用
//虽然obj1和obj2全局作用域下找不到了,但是引用还存在的,obj1和obj2互相在他们的作用域内引用
//用引用计数算法无法释放这部分空间。
function fn() {
    const obj1 = {}
    const obj2 = {}

    obj1.name = obj2
    obj2.name = obj1

    return 'hello world'
}
fn()

这种情况下,就要手动释放变量占用的内存:

obj1.a = null 
obj2.a = null

标记清除:

这个原理实现要比引用计数算法更加简单,还能解决一些问题。在后续学习的v8当中会被大量用到。

核心思想:将整个垃圾回收操作分成标记和清除两个阶段完成。第一个阶段会遍历所有对象,找到活动对象标记。第二个阶段仍然遍历所有对象,把那些身上没有标记的对象进行清除。还会把第一个阶段的标记抹掉,便于GC下次正常工作。通过两次遍历行为,把我们当前的垃圾空间进行回收,最终交给相应的空闲列表去维护。

function fn() { 
    let obj1 = {}; 
    let obj2 = {}; 
    obj1.a = obj2; 
    obj2.a = obj1; 
    return { 
        a: obj1, 
        b: obj2 
    }
}
let obj3 = fn() 

优点 可以找到一些局部作用域的垃圾,可以解决引用计数算法中无法回收循环引用的问题

缺点 在清除垃圾之后,剩余对象的内存位置是不变的,就会导致空闲内存空间不连续,这样就出现了内存碎片,并且由于剩余空间不是整块,就需要内存分配的问题

标记整理

标记整理可以看作是标记清除的增强

标记阶段的操作和标记清除一致

清除阶段会先执行整理,移动对象位置,地址变为连续,这样回收后就可以最大化利用空间

优点:

解决内存碎片化的问题

缺点:

性能消耗大,每一次清楚之前,都要去整理,合并

JavaScript V8 引擎的垃圾回收机制

现在大多数浏览器都是基于标记清除算法,V8 亦是,当然 V8 肯定也对其进行了一些垃圾回收机制的优化。

在JavaScript脚本中,绝大多数对象的生存期很短,只有部分对象的生存期较长。所以,V8 中的垃圾回收主要使用的是 分代回收 (Generational collection)机制。

分代回收机制

V8 中将堆内存分为 新生代 和 老生代 两区域,采用不同的垃圾回收器也就是不同的策略管理垃圾回收。

新生代 的内存一般都不大,所以使用 Scavenge 算法 进行垃圾回收效果比较好。老生代 一般占用内存较大,因此采用的是 标记清除算法。

新生代 的对象为存活时间较短的对象,简单来说就是新产生的对象,通常只支持 1~8M 的容量,而老生代的对象为存活事件较长或常驻内存的对象,简单来说就是经历过新生代垃圾回收后还存活下来的对象,容量通常比较大。

V8 引擎将保存对象的 堆 (heap) 进行了分代,V8 整个堆内存的大小就等于新生代加上老生代的内存(如下图)

新生代垃圾回收

新生代 对象是通过 Scavenge算法 进行垃圾回收,在 Scavenge算法 的具体实现中,主要采用了一种复制式的方法即 Cheney算法 。

Cheney算法 中将堆内存一分为二,一个是处于使用状态的空间我们暂且称之为 使用区,一个是处于闲置状态的空间我们称之为 空闲区,如下图所示。

判断

回到题目,如果你真想检验一个人的水平。第一步先考察一下基本的编程基础,问几个基本的编程问题,可以和前端相关也可以无关。比如垃圾收集大致是怎么做的,setTimeout 大致做了什么(说会在另一个线程里执行回调的直接毙掉)。

第二步考察一下知识面,问问http、tcp的基本知识,dns是怎么工作的,或者常用框架的实现原理,看看候选人是不是除了自己的一亩三分地什么都不关心。

第三步考察hold业务逻辑的能力,从一个简单的注册页,或者查询页开始,先让说下代码的基本架构,然后需求、性能、可靠性、安全层层加码,看看能不能很快的反馈出解决方案。能对答如流的要么做过,要么对他来说这种复杂度的东西是小case。

前三步都没问题,基本上说明候选人已经还行了,但是行到什么程度,不知道。如果想找比较厉害的,就增加个第四步,亮点项目考察。

总的来说,面试官要是考察思路就会从你实际做过的项目入手,考察你实际编码能力,就会让你在电脑敲代码,看你用什么编辑器、插件、编码习惯等。所以我们在回答面试官问题时,有一个清晰的逻辑思路,清楚知道自己在和面试官说项目说技术时的话就好了,我整理一套前端面试题分享给大家,希望对即将去面试的小伙伴们有帮助!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
问题时,有一个清晰的逻辑思路,清楚知道自己在和面试官说项目说技术时的话就好了,我整理一套前端面试题分享给大家,希望对即将去面试的小伙伴们有帮助!

[外链图片转存中…(img-7o24iFDL-1713320399029)]

[外链图片转存中…(img-5Wm9Pleb-1713320399029)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-msm4RegQ-1713320399029)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值