IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 简述JavaScript的垃圾回收机制是什么 -> 正文阅读

[JavaScript知识库]简述JavaScript的垃圾回收机制是什么

JavaScript垃圾回收的必要性

由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。

JS不像C/C++,他有自己的一套垃圾回收机制(Garbage Collection)。JavaScript的解释器可以检测到何时程序不再使用一个对象了,当他确定了一个对象是无用的时候,他就知道不再需要这个对象,可以把它所占用的内存释放掉了。例如:

var a = "before";
var b = "overflow a";
var a = b; //重写a

这段代码运行之后,“before”这个字符串失去了引用(之前是被a引用),系统检测到这个事实之后,就会释放该字符串的存储空间以便这些空间可以被再利用。

JavaScript垃圾回收机制原理解析

●标记清除( mark and sweep )

这是JavaScript最常见的垃圾回收方式。当变量进入执行环境的时候,比如在函数中声明一个变量,垃极回收器将其标记为“进入环境”。当变量离开环境的时候(函数执行结束),将其标记为“离开环境”。

垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量,以及被环境中变量所引用的变量(闭包)的标记。在完成这些之后仍然存在的标记就是要删除的变量。

var a1 = 2;
var b1 = 3;
sum(a1,b1);
function sum(a,b){
   console.log(a+b);
}

如上面这段代码,我们编写一个打印a+b的函数,程序由上到下依次运行,由于JavaScript的预解析,它会提前解析函数,所以我们在声明函数之前调用并不会报错,调用函数时把a1和b1传递给函数a和b,此时垃圾回收器会将a和b标记为进入环境,当调用结束后又将其标记为离开环境,此时,函数中的a,b已经没有引用指向它们,那么它们就将会被垃圾回收机制回收。

●引用计数( reference counting )

在低版本的IE中经常会发生内存泄漏,很多时候就是因为它采用引用计数的方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数。当声明了一个变量并将一个引用类型赋值给该变量的时候,这个值的引用次数就加1. 如果该变量的值变成了另外一个,则这个值的引用次数减1.当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问。因此,可以将它占用的空间回收,这样垃圾回收器会在运行的时候清理引用次数为0的值占用的空间。

function problem() {
    var objA = new Object();
    var objB = new Object();

    obj2.someOtherObject = obj1;
    obj1.anotherObject = obj2;
}

在这里插入图片描述
在这个例子中,Obj1和Obj2通过各自的属性相互引用;也就是说这两个对象的引用次数都是2。在采用引用计数的策略中,由于函数执行之后,这两个对象都离开了作用域,函数执行完成之后,Obj1和Obj2还将会继续存在,因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露(当不断向堆中存储数据,而不进行清理,就会导致内存泄漏)。

在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但是BOM与DOM对象是用引用计数的方式回收垃圾的。也就是说,只要沙及BOM和DOM,就会出现循环引用问题:

var element = document.getElementById("some_element");
var myObj =new Object();
myObj.element = element;
element.someObject = myObj;

上面这个例子中,在一个DOM元素(element)与一个原生JavaScript对象(myObj)之间建立了循环引用。其中,变量myObj有一个名为element的属性指向element;而变量element有一个名为someObject的属性回指到myObj。由于循环引用,即使将例子中的DOM从页面中移除,内存也永远不会回收。

不过上面的问题也不是不能解决,我们可以手动切断他们的循环引用。

myObj.element = null;
element.someObject =null;
  这样写代码的话就可以解决循环引用的问题了,也就防止了内存泄露的问题。

性能优化

1、避免使用全局变量

全局变量会挂载在window下

全局变量至少有一个引用计数

全局变量存活更久,但是持续占用内存

在明确数据作用域的情况下,尽量使用局部变量

2、优化对象

最大限度的实现对象的重用,应该避免使用new语句或{}来新建对象。
删除obj对象的所有属性,高效的将obj转化为一个崭新的对象!
通过清空一个对象来获取“新对象”,比简单的通过{}或new语句来创建对象要耗时一些,但是在实时性要求很高的代码中,这一点短暂的时间消耗,将会有效的减少垃圾堆积,并且最终避免垃圾回收暂停。

3、优化数组

将[]赋值给一个数组对象,是清空数组的捷径(例如: arr = [];),但是需要注意的是,这种方式又创建了一个新的空对象,并且将原来的数组对象变成了一小片内存垃圾!实际上,将数组长度赋值为0(arr.length = 0)也能达到清空数组的目的,并且同时能实现数组重用,减少内存垃圾的产生。

4、减少数据读取次数

1)对于频繁使用的数据,我们要对数据进行缓存。

2)减少循环体中的活动。

3)避开闭包陷阱(将引用对象置为 null 防止闭包中的引用使得不能被回收)

5、尽量避免使用库函数

很多方便使用的Javascript库方法会产生一些新的对象。调用这些库方法,将会创建内存垃圾,避免调用这些方法,将会减少内存的消耗。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 12:40:05  更:2021-11-17 12:41:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 6:57:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码