JS垃圾回收机制

背景:垃圾回收机制是JS引擎的一部分,JS引擎有很多种(各个浏览器都不同),所以垃圾回收机制在一些细节及优化上略有不同。

变量的生命周期

当我们声明变量时候,系统会自动为他们分配内存,JS有两种变量,全局变量和局部变量。全局变量的生命周期会持续到浏览器关闭页面,局部变量的生命周期在函数执行过后就结束了,此时便可将它占用的内存释放。当一个变量的生命周期结束之后它所占用的内存就应该被释放。

栈的垃圾回收策略

(操作系统会为变量自动分配内存)基本数据类型存储在栈内存中,在变量的生命周期结束后,由操作系统自动释放变量所占用的栈内存。

堆的垃圾回收策略

(操作系统会为变量自动分配内存)复杂数据类型存放到堆内存中,复杂数据类型所占用的内存可以由程序员自己释放,如果程序员不释放堆内存,则由垃圾回收机制进行回收。所以垃圾回收机制主要也是针对的是堆内存中的对象。

程序员如何释放,就是将对象在栈里存放的引用赋值为null,则可以释放内存了。

垃圾回收机制是什么?

垃圾回收机制就是周期性的寻找一些不再使用的变量,并释放掉它们所占用的内存。他的作用就是为了防止内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,没有被释放,导致该内存无法被使用。

什么情况会引起内存泄漏?

虽然有垃圾回收机制但是编写代码不规范还是会造成内存泄漏。有以下常见几种情况:

  1. 意外的全局变量引起的内存泄漏。原因是全局变量只有在浏览器关闭才会被销毁,可使用严格模式解决或者规范写代码。
  2. 闭包引起的内存泄露,原因是闭包可以维持函数内局部变量,使其得不到释放。
  3. 被遗忘的定时器
    定时器setInterval或者setTimeout在不需要使用的时候,没有被clear,导致定时器的回调函数及其内部依赖的变量都不能被回收,这就会造成内存泄漏。
    解决方式:当不需要interval或者timeout的时候,调用clearInterval或者clearTimeout
  4. 被遗忘的事件监听器也会造成内存泄漏
    DOM.addEventListener("click", callback)
    垃圾回收机制不好判断该事件是否需要被解除,导致 callback 不能被释放,此时需要手动解除绑定:DOM.removeEventListener(callback)
  5. 循环引用带来的内存泄露,使用引用计数法存在这种问题

垃圾回收算法(了解)

对于程序来说,当一个对象无法被访问或者引用的时候,该对象就是程序中的垃圾了。那垃圾回收机制怎么找出这些对象并且进行释放呢。现在各大浏览器常用的垃圾回收算法有两种:标记清除法和引用计数法。标记清除法是最常用的算法。也是V8引擎使用的算法。

标记清除法

现代浏览器用的大多是基于标记清除法的某些改进算法,总体思想都是一致的。

标记清除法核心思路是什么?
从根部(在JS中就是全局对象)出发定时去扫描内存中的对象,能从根部到达的对象就是还需要使用的,从根部开始无法到达的对象被标记为不再使用,并稍后进行回收。

如下图,右侧那么从根部开始无法访问到的对象,就要被回收。他的优点是可以解决循环引用的问题。

引用计数法

现在各大浏览器基本不再使用引用计数法了,他的核心思路就是记录一个对象被引用的次数,每被引用一次,那么次数就+1,减少一个引用那么次数就减1,如果次数为0则立刻回收这块内存。这种算法的优点就是发现垃圾可以立即进行回收。

引用计数法存在一个致命的问题: 嵌套引用(或者叫循环引用)
如果两个对象相互引用,尽管他们已不再使用,但是他们的引用次数永远不会为0,那么垃圾回收器不会进行回收,导致内存泄露。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值