JavaScript高级:垃圾回收机制

1 引言

垃圾回收机制(Garbage Collection)简称 GC。js中的内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。

 

 2 内存的生命周期

js环境中分配的内存,一般有如下的生命周期:

1. 内存分配:当我们声明变量、函数、对象的时候,系统会自动为它们分配内存;

2. 内存使用:即读写内存,也就是使用变量、函数等;

3. 内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存;

说明:

1. 全局变量一般不会回收(关闭页面才会被回收);

2. 一般情况下局部变量的值,不被使用了,会自动被回收;

3. 程序中分配的内存 由于某种原因,程序未释放或无法释放叫做内存泄漏;(1.下面会提到两个对象相互引用会造成内存泄漏;2. 闭包的一个缺点就是会造成内存泄漏)

3 垃圾回收机制的算法说明

3.1 堆栈空间分配的区别

1. 栈(操作系统):由于操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面;

2. 堆(操作系统):一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收复杂数据类型放到堆里面;

3.2 常见浏览器的垃圾回收算法

3.2.1 引用计数算法

IE 浏览器采用的是引用计数算法,定义 “内存不再使用”, 就是看一个对象是否有指向它的引用,没有被引用了,就回收。

3.2.1.1 算法思路

1. 跟踪记录被引用的次数;

2. 如果被引用了一次,那么记录次数就为1, 多次被引用, 则++;

3. 如果减少一个引用就减一, -- ;

4. 如果引用次数是0, 则释放内存;

3.2.1.2 绘图说明

代码示例1:

const arr = [1, 2, 3]
arr = null

数组是复杂数据类型,所以在栈中存的是地址,arr 通过栈中的地址找到堆中的 [1, 2, 3]

<1>. 当执行第一行代码时:

JavaScript高级:垃圾回收机制_第1张图片

<2>. 当执行第二行代码时:

此时arr被赋值null, null数简单数据类型, 存在栈中

JavaScript高级:垃圾回收机制_第2张图片

<3>. 被引用次数为0,就会自动被回收了


代码示例2;

let person = {
      name: '张三',
      age: 18
}
let person2 = person
person = 1
person = null

<1>. 代码从上往下执行,对象是复杂数据类型,栈中存地址,堆中存的是数据:

JavaScript高级:垃圾回收机制_第3张图片

 

<2>. 当代码执行到 let person2 = person 时

将person赋值给person2, 但是复杂数据类型赋的是地址, 所以此时 perosn2 与 person指向相同的地址, 所以person 和 person2指向堆中相同的数据,引用次数变为了 2

JavaScript高级:垃圾回收机制_第4张图片

<3>.当执行 person = 1 时

 此时person被1赋值, 1属于简单数据类型,存在栈中, 地址改变了,找不到堆中的数据了,所以引用次数减 1

JavaScript高级:垃圾回收机制_第5张图片

<4>.当执行person2 = null 时

跟上面一样,person2被赋值了简单的数据类型,不再指向堆中的数据,被引用次数再次减去1, 变为了0 此时堆中的数据没有被引用了, 会被系统自动回收

JavaScript高级:垃圾回收机制_第6张图片

3.2.1.3 引用计数法存在的问题

嵌套(循环)引用问题

代码示例:

function fn(){
   let obj1 = {}
   let obj2 = {}

   obj1.a = obj2
   obj2.a = obj1

   return '引用次数无法回收!'
}

fn()

<1>.当执行        let obj1 = {}
                          let obj2 = {}     这两行代码时,按道理,函数作用域内属于局部作用域,使用完,会被系统回收,

JavaScript高级:垃圾回收机制_第7张图片


<2>. 但是出现了这两行代码, 问题就出现了,   obj1.a = obj2
                                                                             obj2.a = obj1

JavaScript高级:垃圾回收机制_第8张图片

所以,如果两个对象相互引用,尽管它们已不再被使用,垃圾回收器也不会进行回收,就会导致内存泄漏

3.2.2 标记清除法

JavaScript高级:垃圾回收机制_第9张图片

算法思想:

1. 标记清除法将 “不再引用的对象” 定义为 “无法到达的对象”

2. 就是从根部(在JS中就是从全局对象)出发定时扫描内存中的对象,反是能从根部到达的对象,都是还需要使用的

3. 那些无法从根部出发而触及到的对象被标记为不再使用的,稍后进行回收


JavaScript高级:垃圾回收机制_第10张图片

所以,标记清除法 解决了引用计数法的嵌套引用的问题

你可能感兴趣的:(JavaScript,javascript)