美文网首页
JS的垃圾回收机制与常见内存泄露的解决方法

JS的垃圾回收机制与常见内存泄露的解决方法

作者: Michael113c | 来源:发表于2022-05-29 19:58 被阅读0次

因为项目需要涉及到了垃圾回收机制和内存泄漏,查看网上了许多教程,未免以后遗忘故此记录下来以便以后查阅。

在不需要字符串、对象的时候,需要释放其所占用的内存,否则将会消耗完系统中所有可用的内存,造成系统崩溃,这就是垃圾回收机制所存在的意义

所谓的内存泄漏指的是:由于疏忽或错误造成程序未能释放那些已经不再使用的内存,造成内存的浪费。

垃圾回收

javascript不同于c、c++的一个特点是:具有自动的垃圾回收机制,内存的分配以及内存的回收完全实现了自动管理,减少了许多不必要的麻烦。

所谓的垃圾回收就是找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。
全局变量的生命周期直至浏览器卸载页面才会结束,也就是说全局变量不会被当成垃圾回收

实现垃圾回收的方式主要有两种:标记清除,.引用计数

1.标记清除

目前最常用的垃圾回收的方式,也是当前浏览器所采用的垃圾收集策略。

原理

在标记清除的方式中有两个概念:『进入环境』和『离开环境』。『进入环境』指变量进入执行的环境。『离开环境』指变量完成任务,离开了执行的环境。

当变量进入环境时(例如在函数中声明一个变量),将这个变量标记为“进入环境”,当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

流程

  1. 垃圾收集器在运行的时候给存储在内存中的所有变量都加上标记
  2. 去掉环境中的变量以及被环境中的变量引用的变量的标记
  3. 那些还存在标记的变量则被视为准备删除的变量。
  4. 最后垃圾收集器会执行内存清除的工作,销毁那些带标记的值并回收它们所占用的内存空间

2.引用计数

原理:
引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。
相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这 个值了,因而就可以将其占用的内存空间回收回来。
这样,当垃圾收集器下次再运行时,它就会释放那 些引用次数为零的值所占用的内存。

不过这里潜在的一个问题是:循环引用时,两个对象都至少被引用了一次,将不能自动被回收。所以导致,我们常讲的内存泄露。所以这种机制在js中并不常用。

『循环引用』指的是对象 A 中包含一个指向对象 B 的指针,而对象 B 中也包含一个指向对象 A 的引用。对于像js类的自动回收机制的语言来说,需要额外手动的去释放内存,其实并不友好,例如,在下面的例子中:

function ftc(){
    var A = new Object();
    var B = new Object();
    A.property = B; 
    B.property = A;
}

内存泄漏的原因

虽然js有垃圾回收机制,但我们在编写代码的时候,有些情况还是会造成内存泄漏,了解这些情况,并在编写程序的时候,注意避免,我们的程序会更加完善。

1.上文我们提到了全局变量不会被当成垃圾回收,我们在编码中有时会出现下面这种情况:

 function foo() {
     this.bar2 = '默认绑定this指向全局' // 全局变量=> window.bar2
      bar = '全局变量'; // 没有声明变量 实际上是全局变量=>window.bar
   }
 foo();

当我们使用默认绑定,this会指向全局,this.something也会创建一个全局变量,这一点可能很多人没有注意到。

解决方法:在函数内使用严格模式or细心一点

function foo() {
      "use strict"; 
      this.bar2 = "严格模式下this指向undefined"; 
      bar = "报错";
    }
    foo();

2.当不需要setInterval或者setTimeout时,定时器没有被clear,定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄漏。

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
        node.innerHTML = JSON.stringify(someResource));
        // 定时器也没有清除
    }
    // node、someResource 存储了大量数据 无法回收
}, 1000);

解决方法: 在定时器完成工作的时候,手动清除定时器。

3.循环引用问题,上文有提到

4.没有清理DOM元素引用:
html:

<div id="test">
    <span>1</span>
    <span>2</span>
  </div>

js:

var refA = document.getElementById("test");
document.body.removeChild(refA); // dom删除了
console.log(refA, "refA");  // 但是还存在引用 能console出整个div 没有被回收
refA = null;//解决方法
console.log(refA, "refA");  // 解除引用

5.console保存大量数据在内存中。过多的console,比如定时器的console会导致浏览器卡死。

如何避免内存泄漏

  1. 减少不必要的全局变量,使用严格模式避免意外创建全局变量。
  2. 在你使用完数据后,及时解除引用(闭包中的变量,dom引用,定时器清除)。
  3. 组织好你的逻辑,避免死循环等造成浏览器卡顿,崩溃的问题。

相关文章

  • 2018-10-13

    浅谈浏览器的垃圾回收机制和内存泄露 JavaScript使用垃圾回收机制来自动管理内存。 JS的回收机制分两种:1...

  • java垃圾回收算法

    垃圾回收机制的意义 垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存;内存泄露:指该内存空间使用完毕后未回收,...

  • Java 垃圾回收机制整理

    垃圾回收的意义 如果不进行垃圾回收,内存迟早会被消耗空。垃圾回收机制的引入可以有效的防止内存泄露、保证内存的有效使...

  • JS的垃圾回收机制与常见内存泄露的解决方法

    因为项目需要涉及到了垃圾回收[https://so.csdn.net/so/search?q=%E5%9E%83%...

  • JavaScript内存管理

    JS内存回收 JS 有自动垃圾回收机制,就是找出那些不再继续使用的值,然后释放其占用的内存。 垃圾回收算法: 引用...

  • 对 Java 内存的一些理解-[Android_YangKe]

    Java 垃圾回收机制优点 Java 内存模型 什么是内存抖动 什么是内存泄漏 垃圾回收机制常见算法 Java 垃...

  • js的内存泄露与垃圾回收机制

    前言: 首先读之前我们要了解几个基本概念 基本类型:Undefined/Null/Boolean/Numb...

  • JavaScript的垃圾回收机制

    大纲 1、认识垃圾回收机制2、垃圾回收机制的原理3、垃圾回收机制的标记策略4、垃圾回收机制与内存管理 1、认识垃圾...

  • 常见垃圾回收算法

    什么是垃圾回收(GC) 垃圾回收机制是一种找到内存中的垃圾将其释放并回收空间的机制 常见的垃圾回收算法 引用计数法...

  • 前端面试-JS垃圾回收机制

    什么是垃圾回收机制? JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在...

网友评论

      本文标题:JS的垃圾回收机制与常见内存泄露的解决方法

      本文链接:https://www.haomeiwen.com/subject/eyngprtx.html