js垃圾回收机制原理给你聊的明明白白

前言

大多数语言都是提供自动内存管理机制,比如C#、Java,JavaScript。自动内存管理机制也就是我们经常听到的垃圾回收机制 。好神奇哦,语言会收垃圾,哈哈😄,不过这里的垃圾,可不是家里面的厨余垃圾啥的,而是 一些不再使用的变量所占用的内存。我们的js的执行环境会自动对这些垃圾进行回收,也就是释放那些不再使用的变量所占用的内存,收垃圾的过程 会按照固定的时间间隔周期性的执行 垃圾回收

内存泄露

如果 那些不再使用的变量所占用的内存 没有被释放 会怎样呢??? 那就会造成 内存泄露

什么是内存泄露??? 别着急往下看

内存泄露其实就是我们的程序中已经动态分配的堆内存,由于某些原因没有得到释放,造成系统内存的浪费导致程序运行速度减慢甚至系统崩溃等严重后果。后果很严重的哦,现在知道为啥要有垃圾回收机制了嘛

垃圾回收机制

看看这个代码可以加深理解垃圾回收机制哦☺

1let name = 'Symbol卢'; 2function aboutMe() { 3  let hobby = '吃肉肉'; 4  let say=`我是${name},我喜欢${hobby}`; 5  console.log(say); 6} 7aboutMe()

在函数 aboutMe() 执行的时候,声明了两个局部的变量 hobbysay ,等函数执行完毕之后,这两个局部变量也就不再使用 ,所以垃圾回收机制 就会将不再使用的(局部)变量 hobbysay 清除掉 (释放了它们的内存)

在js中能实现这样的垃圾回收的功能的一共有两种方式: 标记清除引用计数

标记清除

标记清除是js中最常用的垃圾回收方式。它的原理也比较好理解,废话不多说,先上代码

1function speakLines(){ 2  let night="天黑";//做个标记 ,进入环境 3  let closeEyes="闭眼";//做个标记 ,进入环境 4  let speak=`开始狼人杀,${night}${closeEyes}`;//做个标记 ,进入环境 5  console.log(speak); 6} 7speakLines() //代码执行完毕  里面被标记过的变量,又被标记 离开环境 最后被回收

当代码执行在一个环境中时(例如上面的 speakLines函数),每声明一个变量,就会对该变量做一个标记(例如标记一个进入执行环境);当代码执行进入另一个环境中时,也就是要离开上一个环境( speakLines 函数执行完毕,去执行其他的函数),这时对上一个环境中的变量做一个标记,(例如标记一个离开执行环境),等到垃圾回收执行时,会根据标记来决定要清除哪些变量进行释放内存

引用计数

引用计数是一种不太常用的垃圾回收方式。同样也是先上代码再说原理

1let skill = ["唱歌", "弹吉他", "播音"] 2function change() { 3  let new_skill = ["vue", "react", "node", "webpack", ".net", "mysql", "sqlServer", "nginx"]; 4  skill = new_skill; 5  //一个文艺小青年就这样的变成了一个技术宅男 6} 7change() 8console.log(skill)  //返回  ["vue", "react", "node", "webpack", ".net", "mysql", "sqlServer", "nginx"] 9

change()内部声明了一个局部变量 new_skill,并将一个引用类型 的数组 赋值给它,同时又将变量new_skill赋值给了全局变量 skill,此时,这个局部变量 new_skill 就不会被当成垃圾回收了。啊,为什么呢??? 还记得我们在上面说过的 垃圾回收,回收的是那些不再使用的变量,释放它们的内存,因为此时的局部变量 new_skill 并不是一个 不再使用 的局部变量了,它被全局变量 skill所引用了( 还在使用),所以就不会被回收了。

上面的这一过程,使用的就是引用计数的垃圾回收方式

引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值的引用次数减1,当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,当垃圾回收的时候,就会将 引用次数为0的进行回收,释放对应的内存

1let skill = ["唱歌", "弹吉他", "播音"] 2function change() { 3  let new_skill = ["vue", "react", "node", "webpack", ".net", "mysql", "sqlServer", "nginx"];//被引用次数为0 4  skill = new_skill; ////被引用次数为1 5} 6change() 7console.log(skill)

管理内存

在我们的项目中,我们肯定是想要用更少的内存,来使得页面有更好的性能。这个时候就需要我们来手动的管理内存了,及时的去释放数据的引用。我们可以只将需要的数据,存入变量。一旦这个数据不再使用了,我们需要手动的给变量赋值 null 来释放数据的引用。(-------解除引用) 大多需要我们进行手动的解除引用的都是一些全局的变量,因为局部的变量,在离开环境的时候就会被自动清除了。

1let skill = ["唱歌", "弹吉他", "播音"] 2function change() { 3  let new_skill = ["vue", "react", "node", "webpack", ".net", "mysql", "sqlServer", "nginx"] 4  skill = new_skill; 5  //一个文艺小青年就这样的变成了一个技术宅男 6} 7change() 8console.log(skill)  9skill = null;//将不再使用的变量进行赋值 unll  来释放数据引用 10

change() 内部声明的局部变量 new_skill 被全局变量 skill 所引用,所以此时变量 new_skill 的引用次数为1,为了让变量 new_skill 被清除引用,在代码的最后一行,赋值一个 null 给全局变量 skill,手动解除了变量 skill 对变量 new_skill 的引用,此时变量 new_skill 的引用次数 减1,所以 当前 new_skill的引用次数为0了。当垃圾回收机制执行的时候,发现 new_skill 的引用次数为 0,就把该变量当成无用变量给清除了,释放了内存,提高了性能。

历史好文

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java中的GC和内存泄漏

java中的GC1.GC是什么?为什么要有GC? GC是垃圾回收的意思。是指JVM清理不再使用的对象释放内存。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存.2\.需要GC的内存区域垃圾回收区域:主要针对无用堆对象回

Java系列笔记

Java垃圾回收概况  JavaGC(GarbageCollection,垃圾收集,垃圾回收)机制,是Java与C/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM(J

Java 内存区域和GC机制

Java垃圾回收概况  JavaGC(GarbageCollection,垃圾收集,垃圾回收)机制,是Java与C/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM