JavaScript:垃圾回收

JavaScript 是使用垃圾回收的语言。

由执行环境负责在代码执行时管理内存。

垃圾回收 指的是使用垃圾回收程序来实现自动的内存管理,即实现自动的内存分配和闲置资源的回收。

垃圾回收的基本思路:

确定某个变量不会再被使用后,就释放该变量占用的内存。

垃圾回收是周期性的,即垃圾回收程序每隔一段时间(或者说在代码执行过程中某个预定的收集时间)就会运行一次。

垃圾回收的过程是一个近似的、不完美的方案,因为某块内存是否还会被使用,属于“不可判定”的问题,这意味着靠算法是解决不了的。

垃圾回收程序必须记录跟踪变量是否能够被回收,以便能够及时回收内存。

即确定哪些变量还会被使用,哪些变量不会再被使用。


主要参考资料:

  • 《JavaScript 高级程序设计(第4版)》- P94(119/931)

垃圾回收策略

如何记录跟踪不会再被使用的变量有许多的具体实现方式。

在浏览器的发展史上,使用过两个主要的垃圾回收策略:标记清理和引用计数。


标记清理

标记清理是 JavaScript 最常用的垃圾回收策略。

标记清理通过为变量添加标记,来记录跟踪变量是否能够被回收。

从逻辑上讲,在上下文中的变量,在上下文销毁之前不应该释放变量的内存。

所以,当变量进入上下文时,可以为变量添加一个 “存在于当前上下文” 的标记。当变量离开上下文时,为变量添加一个 “离开当前上下文” 的标记。

标记清理的大概过程:

垃圾回收程序运行时,会标记内存中存储的所有变量。然后取消所有在上下文中的变量、被在上下文中的变量引用的变量的标记。之后根据某些情况再次标记某些变量。如此垃圾回收程序执行回收时,可以回收被标记的变量的内存。

标记的具体的实现方式有很多种。(不展开叙述)


引用计数

引用计数通过记录每个值被引用的次数,来记录跟踪变量是否能够被回收。

当声明一个变量并给它赋值为一个引用值时,这个被引用的值的引用数为 1 。当一个新的变量引用这个值时,这个值的引用数加 1 。相应的,当引用这个值的变量不再引用这个值时,这个值的引用数减 1 。当一个值的引用次数为 0 时,表示可以回收这个值。

但引用计数不能很好地处理变量之间的循环引用。

当对象 a 、对象 b 相互引用对方作为自己的属性时,就在对象 a 和对象 b 之间形成了一个 循环引用

示例:

  • 循环引用。
    let objA = new Object()
    let objB = new Object()
    
    // 循环引用
    objA.b = objB
    objB.a = objA
    

此时即使外部没有变量引用它们的值,它们的值的引用数依然为 2 ,即对象 a 被引用自身的变量、对象 b 的属性引用。

这就对取消对值的引用的顺序有了要求:

  • 如果想要使形成循环引用的对象 a 、对象 b 的引用数为 0 ,就必须先各自取消自身属性对对方的引用,然后再各自取消引用自身的变量对自身的引用。

    示例:

    let objA = new Object()
    let objB = new Object()
    
    objA.b = objB
    objB.a = objA
    
    // 先各自取消自身属性对对方的引用
    objA.b = null
    objB.a = null
    
    // 再取消各自的变量对自身的引用
    objA = null
    objB = null
    
  • 如果在取消自身属性对对方的引用之前,取消引用自身的变量对自身的引用,会导致之后无法获取自身属性,从而导致无法进行取消自身属性对对方的引用的操作,最终导致在程序运行期间,对方的引用数的最小值永远为 1 。

    示例:

    let objA = new Object()  // 将此时变量 objA 引用的值记为对象 a 
    let objB = new Object()  // 将此时变量 objB 引用的值记为对象 b 
    
    objA.b = objB
    objB
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值