【深入学习JS】06_垃圾回收机制

本文介绍了JavaScript的内存生命周期,包括自动分配和释放内存。垃圾回收机制主要采用标记清除算法,避免了引用计数带来的循环引用问题。同时,文中列举了常见的内存泄漏案例,如全局变量、闭包和DOM引用,提醒开发者注意合理管理内存。
摘要由CSDN通过智能技术生成

前言

上一文在介绍堆内存和栈内存的时候,提到了垃圾回收机制。JavaScript具有自动垃圾回收机制,会定期堆那些我们不再使用的变量所占有的内存进行释放。

内存生命周期

  • 分配你所需的内存:在JS中,不管是进行值的初始化,还是通过函数调用,都会自动帮其分配内存,如果是基本类型久存储在栈内存中,如果是引用类型,就将其存储在堆内存中,并将指向堆内存地址的指针存储在栈内存中;
  • 使用分配到的内存:当我们要对变量进行读取或者写入的时候,就去内存中查找(修改)他们的值;
  • 不需要时将内存释放:JS的自动垃圾回收机制,会跟踪内存的分配和使用,以便变量不再被使用时,自动释放它。

垃圾回收机制

JS如何辨别那些值是可以回收的呢?这时候就需要了解一下垃圾回收算法了。垃圾回收算法主要分两种:

  • 引用计数;
  • 标记清除。

引用计数

主要是统计引用类型变量声明后被引用的次数,当次数为0时,这个变量将会被收回。

const o = {};
let a = o;   // o被a引用,计数为1
let b = o;   // o被b引用,计数为2
a = {};      // a不再引用o, 计数为1
b = null;    // a不再引用o, 计数为0, 这时候o将被回收

但是引用计数有一个缺点,叫做循环引用。

const o1 = {};
const o2 = {};
o1.test = o2;
o2.test = o1;

o1、o2互相引用,计数永远不可能为0,所以建议在不需要o1、o2时,手动设置为null,解除引用。

标记清除

当变量进入环境时,标记为“进入环境”,当变量离开环境时,将标记为“离开环境”,此时,这个变量将会被收回。具体做法如下:

  • JS开始运行时,会给存储在内存中的所有变量加上标记;
  • 然后去掉环境中的变量和被环境中的变量引用的变量的标记;
  • 此后,再被加上标记的变量被视为准备删除的变量;
  • 最后,垃圾收集器,销毁那些带有标记的值,并释放它们的内存空间。
function foo(){
    const a = 'a';
    const b = 'b';
}

foo();

当执行foo时,建立执行上下文,此时a、b进入环境;当执行完毕之后,a、b离开环境,最后,a、b会被垃圾收集器销毁,并释放它们的内存空间。

从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。

常见的内存泄露案例

当JS环境中存在不需要的内存,但是由于没有被释放,造成了内存泄漏。

全局变量

function foo(){
    name = '王花花';
}
foo();

执行foo时,由于name前面缺少var,先在当前作用域寻找name,没找到,于是向上一级的全局作用域寻找,这里也没有,于是会自动在全局作用域进行声明,所以会把var定义到全局作用域中,当foo执行完毕,但name这个全局变量,并不会被销毁,导致了name内存泄漏。

闭包

function foo(){
    var a = 'a';
    function bar(){
        console.log(a);
    }
    return bar;
}

const test = foo();
test();             //  a

foo虽然执行完毕了,但是将bar返回给了test,所以此时foo内的变量还被引用着,所以造成了内存泄漏。

DOM引用

let el = document.getElementById('el');
el.text = '123';
document.body.removeChild(document.getElementById('el'));
console.log(el.text);     // 123

即使我们对el元素移除,但是el变量仍旧保留对DOM的引用,所以造成了内存的泄漏。

总结

  • JS的垃圾回收机制是定期自动执行的;
  • 垃圾回收机制算法有标记清除和引用计数;
  • 不合理的代码会造成内存泄漏。

参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值