前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >谈谈JavaScript的垃圾回收

谈谈JavaScript的垃圾回收

作者头像
何处锦绣不灰堆
发布2022-05-18 11:03:57
3850
发布2022-05-18 11:03:57
举报
文章被收录于专栏:农历七月廿一农历七月廿一

什么是内存管理

对内存的产生、分配、释放的过程就叫做内存管理

为什么要有内存管理

任何一门编程语言都有自己的内存管理的机制,有一些语言底层封装了一些内存回收的接口和方法,那么js中其实也有,我们叫做垃圾回收,不过js的相对比较混乱,原因是我们在创建和分配的过程没问题,但是释放的时候是自动释放,所以导致很多“垃圾”并不会得到合理的释放,就因为js是自动释放导致我们写js代码的程序员们觉得不需要对js代码中存在的内存问题进行处理,最后会导致代码中出现很多难以回收的内存,造成内存泄漏!

js中内存的分配方式

js的内存分配应该是众多语言中最简单的,我们在声明变量的时候系统就会分配一块内存给到我们,代码如下:

  • 声明变量分配内存
代码语言:javascript
复制
let num = 999
let _str = "str"
let obj = {
  name : 'jim'
}
function f(){
  return true
}
  • 函数调用分配内存
代码语言:javascript
复制
let t = new Date()
let buffer = new ArrayBuffer(32)
let e = document.createElement('div')
  • js内置方法分配新变量进行分配内存
代码语言:javascript
复制
let r = [1,2,3]
let s = r.join(',')

内存管理的方式-存在的问题

这里要说的是js对内存的管理,前面也说了,就是创建、使用、释放的过程,那么创建和使用其实都是比较简单的,因为这个过程语言本身是可以知道的,但是释放的时机就不太好把握了,语言本身没办法很直接准确的知道什么时候应该释放内存,说白了就是按照一个什么样的标准判断这个变量是不是已经可以被释放了,另外的一种问法就是语言怎么知道变量不被使用了,因为只要一个变量不被使用了,理论上就是可以被释放的,很多语言的垃圾回收难点都在这里,没办法很准确的知道哪一块内存是不被使用了!

垃圾回收方式一 [引用计数垃圾收集]

这个方式简单来说就是js将问题简单化了,他将代码中对象(不仅仅包含变量,还有函数和前面提过的几种情况)是否还需要定义为了这个对象是不是被引用了,意思就是说,对象只要一直被任何对象引用,都被认为是“有用的,不可以被回收的”

  • 代码示例
代码语言:javascript
复制
//两个对象被创建 a 和 c
let a = {
  name : "jim", 
  c : {
    child : "str"
  }
}
//a被b使用
let b = a.name
//a被c使用 c被两个引用 一个是a  一个是c1
let c1 = a.c
// c被d引用了
let d = c1
//此时d = 0 那么 c1不被引用了,可以被垃圾回收了,但是c还不行,因为被a引用
d = 0
//a = null a也没有引用了,可以被回收了
a = null
引用计数垃圾收集-弊端
  • 代码示例
代码语言:javascript
复制
function n(){
  let x = {}
  let y = {}
  x.a = y
  y.a = x
  return true
}
n()

上述代码中 x、y相互引用,但是被调用之后离开了函数作用域,因为你已经return出去了,所以这个时候按照上面的引用计数垃圾收集的方式就行不通了,因为他检测到还有被引用的,所以他不会被机制回收!说的简单一点就是这种机制比较笨,他只要检测到你有被引用,就不会回收你,所以,在IE比较早的一些版本的时候,容易造成内存泄漏也是这个原因导致的,我们操作dom的时候,不会主动释放内存,代码就一直认为他被引用,所以一直不会主动回收!

垃圾回收方式一 [标记算法]

这种方式其实相对更加的容易理解,我不管你是不是被引用了,我只关心你是不是可以被我获取到,如果可以被获取到,那么你就是有用的,这么说可能不太严谨,因为我直接定义一个变量理论上也是可以被找到的,但是我没有被引用,其实还是应该被回收的,这个的机制本身的一个算法过程是,js假设有一个Root根节点,可以理解为一个全局对象,js会定期从根节点开始查找,然后找对象引用的对象,那么最后找到所有可以获取到的对象和获取不到的对象,如果你是一个从不被引用的对象,那么根节点开始一定是找不到你的,所以你就会被回收!那么上面的那个弊端的问题就不存在了,因为函数被调用之后他将不会被根节点找到,自然就会被回收!

写在最后

类似这种垃圾回收的东西其实是比较枯燥乏味的,但是了解他有助于我们更好的优化性能,因为很多时候不管代码的机制多么的智能,我们还是希望自己写代码的时候可以主动告诉浏览器哪些是可以被回收了,哪些是我在使用的,感谢大家的阅读,拜了个白!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是内存管理
  • 为什么要有内存管理
  • js中内存的分配方式
  • 内存管理的方式-存在的问题
  • 垃圾回收方式一 [引用计数垃圾收集]
    • 引用计数垃圾收集-弊端
    • 垃圾回收方式一 [标记算法]
    • 写在最后
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档