05_内存机制

一. JS的数据类型

JavaScript是一种弱类型的、动态的语言

弱类型:支持隐式类型转换的语言,与强类型对应

动态语言:在运行过程中需要检查数据类型的语言,与静态语言对应

原始类型

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol
  • BigInt

引用类型

  • Object

二. 内存空间

代码空间

栈空间

  • 调用栈
  • 原始类型的数据值直接保存在栈中
  • 原始类型的赋值会完整复制变量值

堆空间

  • 引用类型的值存放在堆中
  • 引用类型的赋值是复制引用地址
// 原始类型
function foo(){
 var a = 1
 var b = a
 a = 2
 console.log(a) // 2
 console.log(b) // 1
}
foo()

// 引用类型 
function foo(){
 var a = {name:" 极客时间 "}
 var b = a
 a.name = " 极客邦 " 
 console.log(a) // {name:"极客邦"}
 console.log(b) // {name:"极客邦"}
}
foo()

内存模型下的闭包

  • 产生闭包的核心步骤
    1. 预扫描内部函数
    2. 把内部函数引用的外部变量保存到堆中closure的对象里

三. 垃圾数据回收

手动回收:分配内存、销毁内存都是由代码控制(如C++语言),容易造成内存泄漏

自动回收:垃圾数据由垃圾回收器来释放(如JS)

1. 调用栈中的数据回收

ESP:记录当前执行状态的指针

function foo(){
 	var a = 1
 	var b = {name:" 极客邦 "}
 	function showName(){
 	var c = " 极客时间 "
 	var d = {name:" 极客时间 "}
 }
 showName()
}
foo()

说明

​ 执行到showName函数时,这一函数的执行上下文压入栈,并且ESP指向showName函数的执行上下文。

​ 当showName函数执行完成后,ESP向下移动到foo函数的执行上下文,showName函数的执行上下文虽然仍旧被保存在栈内存中,但已经是无效内存,可以被覆盖。

总结:JavaScript 引擎会通过向下移动 ESP 来销毁该函数保存在栈中的执行上下文

2堆中的数据回收

  • 需要使用垃圾回收器
  • 以 JavaScript 引擎 V8 为例

代际假说:

  • 大部分对象在内存中存在的时间很短,简单来说,就是很多对象一经分配内存, 很快就变得不可访问
  • 不死的对象,会活得更久
  • V8把堆分为两个区域
    • 新生代:存放生存时间短的对象,1~8M的容量,使用副垃圾回收器
    • 老生代:存放生存时间久的对象,容量很大,使用主垃圾回收器
垃圾回收器工作流程
  1. 标记空间中活动对象和非活动对象。
    • 活动对象就是还在使用的对象
    • 非活动对象就是可以进行垃圾回收的对象。
  2. 回收非活动对象所占据的内存。其实就是在所有的标记完成之后,统一清理内存中所有被标记为可回收的对象。
  3. 内存整理。当内存中出现了大量的内存碎片之后,如果需要分配较大连续内存的时候,就有可能出现内存不足的情况。所以最后一步需要整理这些内存碎片。
    • 内存碎片:频繁回收对象后,内存中出现的大量不连续空间
    • 这步可选,因为有的垃圾回收器不会产生内存碎片,比如副垃圾回收器
1. 副垃圾回收器

Scavenge 算法:把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域。

新加入的对象都会存放到对象区域,当对象区域快被写满时,就需要执行一次垃圾清理操作

  • 流程:

      1. 对对象区域中的垃圾做标记
      2. 垃圾清理阶段,副垃圾回收器会把这些存活的对象复制到空闲区域中,同时它还会把这些对象有序地排列起来
      3. 完成复制后,对象区域与空闲区域进行角色翻转,也就是原来的对象区域变成空闲区域,原来的空闲区域变成了对象区域。
  • 说明:

    • 第2步完成了内存整理,复制后空闲区域没有内存碎片
    • 第3步能让新生区的两块区域无限重复使用
    • 对象晋升策略:经过两次垃圾回收依然还存活的对象, 会被移动到老生区中。
2. 主垃圾回收器

标记 - 清除算法:标记垃圾数据后直接进行清除

标记 - 整理算法:让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

  • 流程:

      1. 标记过程阶段。标记阶段就是从一组根元素开始,递归遍历这组根元素,在这个遍历过程中,能到达的元素称为活动对象,没有到达的元素就可以判断为垃圾数据
      2. 垃圾的清除过程。执行标记-整理算法,清除垃圾数据
  • 说明:

    • 标记-清除算法会产生大量不连续内存碎片,所以采用标记-整理算法
    • 增量标记算法:V8 将标记过程分为一个个的子标记过程,同时 让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成。为了降低垃圾回收造成的全停顿

全停顿:执行垃圾回收算法时都将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。

学习资料

李兵:《12丨栈空间和堆空间:数据是如何存储的?》
《13丨垃圾回收:垃圾数据是如何自动回收的?》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值