• js垃圾回收机制


    1.内存泄漏

    程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。
    对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。
    也就是说,不再用到的内存,如果没有及时释放,就叫做内存泄漏。

    1.1 哪些操作会造成内存泄漏:

    1.1.1 意外的全局变量

    
    function fn(){	
    	a = "123"; //a成为一个全局变量,不会被回收
    }
    
    // 上面的写法等价于
    function fn() {
    	window.a = '123'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    由于没有使用var来声明,a变量会被创建成全局变量,会造成内存泄漏
    解决方式:
    在js文件开头添加 ‘use strict’,开启严格模式。

    1.1.2 未清理的DOM元素引用

    var a = document.getElementById('id');
    document.body.removeChild(a);
    
    • 1
    • 2

    不能回收,因为存在变量a对它的引用。虽然我们用removeChild移除了,但是还在对象里保存着#的引用,即DOM元素还在内存里面。

    解决方法: a=null

    1.1.3 被遗忘的定时器或者回调

    解决方式: 当不需要interval或者timeout的时候,调用clearInterval或者clearTimeout

    1.1.4 闭包

    Javascript 闭包

    1.1.5 console.log

    传递给console.log的对象是不能被垃圾回收,所以没有去掉console。log可能会存在内存泄漏

    2.JavaScript中的垃圾回收

    垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。

    垃圾回收器会跟踪哪个变量没用,对于不再有用的变量打上标记,以备将来收回其内存,用于标记无用变量的策略可能因实现而有所区别,通常情况下有两种实现方式:标记清除引用计数

    2.1 标记清除

    JavaScript 中最常用的垃圾回收方式就是标记清除。

    function test(){
      var a = 10 ; // 被标记 ,进入环境 
      var b = 20 ; // 被标记 ,进入环境
    }
    test(); // 执行完毕 之后 a、b 又被标离开环境,被回收。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当变量进入环境时,就将这个变量标记为“进入环境”,而当变量离开环境时,则将其标记为“离开环境”。

    垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中变量的标记 以及被环境中的变量引用的变量(闭包)的标记。而在此之后在被加上标记的变量将被视为准备删除的变量。
    最后,垃圾回收器完成内存清除功工作,销毁那些带标记的值并会搜狐他们所占用的内存空间。

    到目前为止,IE9+、Firefox、Opera、Chrome、Safari 的 JS 实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同

    2.2 引用计数

    引用计数:跟踪记录每个值被引用的次数
    当声明一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值被赋值给另一个变量,则该值的引用次数加1。

    如果包含这个值引用的变量又取得了另一个值,则这个值的引用次数减1。

    当垃圾回收器下次再运行时,就会释放那些引用次数为0的值所占用的内存。

    function test() {
        var a = {};	// a 指向对象的引用次数为 1
        var b = a;	// a 指向对象的引用次数加 1,为 2
        var c = a;	// a 指向对象的引用次数再加 1,为 3
        var b = {};	// a 指向对象的引用次数减 1,为 2
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    遇到的问题:循环引用
    对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用

    function fn() {
        var a = {};
        var b = {};
        a.pro = b;
        b.pro = a;
    }
    fn();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    a和b的引用次数都是2,fn执行完毕后,因为a和b的引用次数不为0,所以不会被垃圾回收内存,如果fn函数大量使用,就会造成内存泄漏。

  • 相关阅读:
    pdf相关的python库
    Spring 最常用的几个注解
    数据挖掘实战应用案例精讲-【概念篇】数据湖(补充篇)(Data Lake )
    Docker基础篇
    【转载】 Bytedance火山引擎智能拥塞控制算法 VICC
    [附源码]计算机毕业设计校园招聘微信小程序Springboot程序
    Go 学习笔记(87) — 函数式选项,初始化结构体对象可变参数
    VUE前端HTML静默打印(不弹出打印对话框)PDF简单方案
    C Primer Plus(6) 中文版 第1章 初识C语言 1.1 C语言的起源 1.2 选择C语言的理由 1.3 C语言的应用范围
    Vue学习:分析hello案例
  • 原文地址:https://blog.csdn.net/weixin_44247866/article/details/126111573