今天小编给大家分享的是javascript有垃圾回收机制gc吗,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。

成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站制作、成都网站设计、惠农网络推广、重庆小程序开发、惠农网络营销、惠农企业策划、惠农品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联公司为所有大学生创业者提供惠农建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com
javascript中有GC(垃圾回收机制)。JavaScript是使用垃圾回收机制的语言,执行环境负责在代码执行时管理内存,会自动将垃圾对象(没有被引用的对象)从内存中销毁。
JavaScript 中的垃圾回收机制(GC)
垃圾回收相关概念
① 什么是垃圾
没有被使用(引用)的对象就是垃圾。
② 什么是垃圾回收
没有被引用的对象被销毁,内存被释放,就是垃圾回收。
C、C++ 等编程语言需要手动垃圾回收。
Java、JavaScript、PHP、Python 等语言自动垃圾回收。
JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作。我们需要做的只是要将不再使用的对象设置为 null 即可。
为什么需要垃圾回收
- 在C / C++中,跟踪内存的使用和管理内存对开发者来说是很大的负担 
- JavaScript是使用垃圾回收机制的语言,也就是说执行环境负责在代码执行时管理内存,帮开发者卸下了这个负担 
- 通过自动内存管理实现内存的分配和资源的回收 
- 基本思路很简单,确定哪个变量不会再被使用了,把它的内存空间释放 
- 这个过程是周期性的,意思是这个垃圾回收程序每隔一段时间就会运行一次 
- 像JS中的对象、字符串、对象的内存是不固定的,只有真正用到的时候才会动态分配内存 
- 这些内存需在不使用后进行释放以便再次使用,否则在计算机可用内存耗尽后造成崩溃 
- 浏览器发展史上的垃圾回收法主要有 
- 引用计数法 
- 标记清除法 
引用计数法
思路
- 变量只是对值进行引用 
- 当变量引用该值时,引用次数+1 
- 当该变量的引用被覆盖或者清除时,引用次数-1 
- 当引用次数为0时,就可以安全地释放这块内存。 
let arr = [1, 0, 1] // [1, 0, 1]这块内存被arr引用 引用次数为1 arr = [0, 1, 0] // [1, 0, 1]的内存引用次数为0被释放 // [0, 1, 0]的内存被arr引用 引用次数为1 const tmp = arr // [0, 1, 0]的内存被tmp引用 引用次数为2
循环引用问题
Netscape Navigator 3.0 采用
- 在这个例子中,ObjectA和ObjectB的属性分别相互引用 
- 造成这个函数执行后,Object被引用的次数不会变成0,影响了正常的GC。 
- 如果执行多次,将造成严重的内存泄漏。 
- 而标记清除法则不会出现这个问题。 
function Example(){
    let ObjectA = new Object();
    let ObjectB = new Object();
    ObjectA.p = ObjectB;
    ObjectB.p = ObjectA;   
}
Example();- 解决方法:在函数结束时将其指向null 
ObjectA = null; ObjectB = null;
标记清除法
为了解决循环引用造成的内存泄漏问题,Netscape Navigator 4.0 开始采用标记清除法
到了 2008 年,IE、Firefox、Opera、Chrome 和 Safari 都在自己的 JavaScript 实现中采用标记清理(或 其变体),只是在运行垃圾回收的频率上有所差异。
思路
- 在变量进入执行上下文时打上“进入”标记 
- 同时在变量离开执行上下文时也打上“离开”标记 
- 从此以后,无法访问这个变量 
- 在下一次垃圾回收时进行内存的释放 
function Example(n){
    const a = 1, b = 2, c = 3;
    return n * a * b * c;
}
// 标记Example进入执行上下文
const n = 1;  // 标记n进入执行上下文
Example(n);   // 标记a,b,c进入执行上下文
console.log(n); // 标记a, b, c离开执行上下文,等待垃圾回收const和let声明提升性能
- const和let不仅有助于改善代码风格,同时有利于垃圾回收性能的提升 
- const和let使JS有了块级作用域,当块级作用域比函数作用域更早结束时,垃圾回收程序更早介入 
- 尽早回收该回收的内存,提升了垃圾回收的性能 
V8引擎的垃圾回收
V8引擎的垃圾回收采用标记清除法与分代回收法
分为新生代和老生代
新生代
新生代垃圾回收采用
Scavenge算法
分配给常用内存和新分配的小量内存
- 内存大小 
- 32位系统16M内存 
- 64位系统32M内存 
- 分区 
- 新生代内存分为以下两区,内存各占一半 
- From space 
- To space 
- 运行 
- 实际运行的只有From space 
- To space处于空闲状态 
- Scavenge算法
- 解决了内存散落分块的问题(不连续的内存空间) 
- 相当于用空间换时间。 
- 当From space内存使用将要达到上限时开始垃圾回收,将From space中的不可达对象都打上标记 
- 将From space的未标记对象复制到To space。 
- 然后清空From space、将其闲置,也就是转变为To space,俗称反转。 
- 新生代 -> 老生代 
- 内存大小达到From space的25% 
- 经历了From space <-> To space的一个轮回 
- 新生代存放的是新分配的小量内存,如果达到以下条件中的一个,将被分配至老生代 
老生代
老生代采用
mark-sweep标记清除和mark-compact标记整理
通常存放较大的内存块和从新生代分配过来的内存块
- 内存大小 
- 32位系统700M左右 
- 64位系统1.4G左右 
- 分区 
- 存储编译后的代码 
- 存放存储对象的映射关系 
- 存放其他区域放不下的较大的内存,基本都超过1M 
- 字面的老生代,存放的是新生代分配过来的内存。 
- Old Object Space 
- Large Object Space 
- Map Space 
- Code Space 
- 回收流程 
- 标记完成之后,将标记为 - 1类的对象进行内存释放
- 采用深度优先遍历,遍历每个对象。 
- 首先将非根部对象全部标记为 - 1类,然后进行深度优先遍历。
- 遍历过程中将对象压入栈,这个过程中对象被标记为 - 2类。
- 遍历完成对象出栈,这个对象被标记为 - 3类。
- 整个过程直至栈空 
- 未被扫描,可回收,下面简称 - 1类
- 扫描中,不可回收,下面简称 - 2类
- 扫描完成,不可回收,下面简称 - 3类
- 标记分类(三色标记) 
- 遍历 
- Mark-sweep 
- Mark-compact 
- 垃圾回收完成之后,内存空间是不连续的。 
- 这样容易造成无法分配较大的内存空间的问题,从而触发垃圾回收。 
- 所以,会有Mark-compact步骤将未被回收的内存块整理为连续地内存空间。 
- 频繁触发垃圾回收会影响引擎的性能,内存空间不足时也会优先触发Mark-compact 
垃圾回收优化
- 增量标记 
- 如果用集中的一段时间进行垃圾回收,新生代倒还好,老生代如果遍历较大的对象,可能会造成卡顿。 
- 增量标记:使垃圾回收程序和应用逻辑程序交替运行,思想类似Time Slicing 
- 并行回收 
- 在垃圾回收的过程中,开启若干辅助线程,提高垃圾回收效率。 
- 并发回收 
- 在逻辑程序执行的过程中,开启若干辅助线程进行垃圾回收,清理和主线程没有任何逻辑关系的内存。 
内存泄露场景
全局变量
// exm1
function Example(){
    exm = 'LeBron'   
}
// exm2
function Example(){
    this.exm = 'LeBron'
}
Example()未清除的定时器
const timer = setInterval(() => {
    //...
}, 1000)
// clearInterval(timer)闭包
function debounce(fn, time) {
  let timeout = null; 
  return function () {
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fn.apply(this, arguments);
    }, time);
  };
}
const fn = debounce(handler, 1000); // fn引用了timeout未清除的DOM元素引用
const element = {
    // 此处引用了DOM元素
    button:document.getElementById('LeBron'),
    select:document.getElementById('select')
}
document.body.removeChild(document.getElementById('LeBron'))如何检测内存泄漏
这个其实不难,浏览器原带的开发者工具Performance就可以
- 步骤 
- F12打开开发者工具 
- 选择Performance工具栏 
- 勾选屏幕截图和Memory 
- 点击开始录制 
- 一段时间之后结束录制 
- 结果 
- 堆内存会周期性地分配和释放 
- 如果堆内存的min值在逐渐上升则存在内存泄漏 
优化内存使用
1、尽量不在for循环中定义函数
// exm
const fn = (idx) => {
    return idx * 2;
}
function Example(){
    for(let i=0;i<1000;i++){
        //const fn = (idx) => {
        //    return idx * 2;
        // }
        const res = fn(i);
    }
}2、尽量不在for循环中定义对象
function Example() {
  const obj = {};
  let res = "";
  for (let i = 0; i < 1000; i++) {
    // const obj = {
    //   a: i,
    //   b: i * 2,
    //   c: i * 3,
    // };
    obj.a = i;
    obj.b = i * 2;
    obj.c = i * 3;
    res += JSON.stringify(obj);
  }
  return res
}3、清空数组
arr = [0, 1, 2] arr.length = 0; // 清空了数组,数组类型不变 // arr = [] // 重新申请了一块空数组对象内存
关于javascript有垃圾回收机制gc吗就分享到这里了,希望以上内容可以对大家有一定的参考价值,可以学以致用。如果喜欢本篇文章,不妨把它分享出去让更多的人看到。
网站标题:javascript有垃圾回收机制gc吗
本文路径:http://www.scyingshan.cn/article/gddgpd.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 