搜索
首页web前端js教程一张纸搞懂JS系列(3)之垃圾回收机制,内存泄漏,闭包
一张纸搞懂JS系列(3)之垃圾回收机制,内存泄漏,闭包Sep 30, 2020 pm 04:38 PM
内存泄漏垃圾回收机制闭包

javascript栏目为大家介绍垃圾回收机制,内存泄漏,闭包的内容,快端小板凳来看看啦。

一张纸搞懂JS系列(3)之垃圾回收机制,内存泄漏,闭包

写在最前面:这是javascript栏目我即将开始写的一个系列,主要是在框架横行的时代,虽然上班用的是框架,但是对于面试,以及技术进阶,JS基础知识的铺垫是锦上添花,也是不得不学习的一块知识,虽然开汽车的不需要很懂汽车,只需要掌握汽车的常用功能即可。但是如果你懂汽车,那你也能更好地开车,同理。当然,一篇文章也不会光光只讲一个知识点,一般会将有关联的知识点串联起来,一边记录自己的学习,一边分享自己的学习,互勉!如果可以的话,也请给我点个赞,你的点赞也能让我更加努力地更新!

概览

  • 食用时间: 6-12分钟
  • 难度: 简单,别跑,看完再走

垃圾回收机制

前面一篇博客主要讲解了内存的分配和使用(栈内存与堆内存,深拷贝与浅拷贝),使用完了以后,当然是要将不使用的内存归还,就像将手机上不使用的软件从后台清除,可以提升手机的运行速度,不然越来越多,迟早会卡, JS 也是一样的。

每隔一段时间, JS垃圾收集器都会对变量进行“巡逻”,就和保安巡逻园区一样,让不相干的人赶紧走。当一个变量不被需要了以后,它就会把这个变量所占用的内存空间所释放,这个过程就叫做垃圾回收

JS 的垃圾回收算法分为两种,引用计数法和标记清除法

  • 引用计数法

    引用计数法是最初级的垃圾回收算法,已经被现代浏览器所淘汰了。在学习引用计数法之前,需要首先对引用有一定的概念,你可以认为它就是对当前变量所指向的那块内存地址的描述,有点类似于JS引用数据类型的内存指向的概念,先来看一行代码:

    var obj={name:'jack'};复制代码

    当我们在给 obj 赋值的同时,其实就创建了一个指向该变量的引用,引用计数为1,在引用计数法的机制下,内存中的每一个值都会对应一个引用计数

    而当我们给 obj 赋值为 null时,这个变量就变成了一块没用的内存,那么此时, obj 的引用计数将会变成 0,它将会被垃圾收集器所回收,也就是 obj 所占用的内存空间将会被释放

    我们知道,函数作用域的生命周期是很短暂的,在函数执行完毕之后,里面的变量基本是没用的变量了,不清除的后果就是该内存垃圾没有被释放,依然霸占着原有的内存不松手,就会容易引发内存泄漏,先来看一段代码以及运行结果:

    function changeName(){   var obj1={};   var obj2={};
       
       obj1.target=obj2;
       obj2.target=obj1;
       obj1.age=15;   console.log(obj1.target);   console.log(obj2.target);
    }
    
    changeName();复制代码
    一张纸搞懂JS系列(3)之垃圾回收机制,内存泄漏,闭包
    我们可以看到, obj1.targetobj2.target 存在互相引用的情况,因为在改变 obj1.age 的同时,obj1.target.ageobj2.target.age 也同时都被影响到了,它们所指向的引用计数是一致的

    在函数执行完毕的时候, obj1obj2 还是活的好好地,因为 obj1.targetobj2.target 的引用计数在执行完毕之后,仍然是 1 ,明明函数执行完毕,但是这种垃圾依然存在,这种函数定义多了,内存泄漏也会是无法避免的

  • 标记清除法

    上面的引用计数法的弊端已经很明显了,那么,现在所要说的标记清除法就不存在这样子的问题。因为它采用的判断标准是看这个对象是否可抵达,它主要分为两个阶段,标记阶段清除阶段:

    • 标记阶段

      垃圾收集器会从根对象(Window对象)出发,扫描所有可以触及的对象,这就是所谓的可抵达

    • 清除阶段 在扫描的同时,根对象无法触及(不可抵达)的对象,就是被认为不被需要的对象,就会被当成垃圾清除

    现在再来看下上面的代码

    function changeName(){    var obj1={};  var obj2={};
      
      obj1.target=obj2;
      obj2.target=obj1;
      obj1.age=15;  console.log(obj1.target);  console.log(obj2.target);
    }
    
    changeName();复制代码

    在函数执行完毕之后,函数的声明周期结束,那么现在,从 Window对象 出发, obj1obj2 都会被垃圾收集器标记为不可抵达,这样子的情况下,互相引用的情况也会迎刃而解。

内存泄漏

该释放的内存垃圾没有被释放,依然霸占着原有的内存不松手,造成系统内存的浪费,导致性能恶化,系统崩溃等严重后果,这就是所谓的内存泄漏

闭包

  • 定义与特性

    闭包是指有权访问另一个函数作用域中的变量的函数。至于为什么有权访问,主要是因为作用域嵌套作用域,也就是所谓的作用域链,关于作用域链不清楚的可以看我的第一篇博客一文搞懂JS系列(一)之编译原理,作用域,作用域链,变量提升,暂时性死区,就是因为作用域链的存在,所以内部函数才可以访问外部函数中定义的变量 ,作用域链是向外不向内的,探出头去,向外查找,而不是看着锅里,所以外部函数是无法访问内部函数定义的变量的。并且,还有一个特性就是将闭包内的变量始终保持在内存中。

    前面的作用域向外不向内,这里就不再做过多解释了,我们主要来看我后面说的特性,那就是闭包内的变量始终保存在内存中

    来看一下阮一峰教程当中的一个例子

     function f1(){     var n=999;
    
         nAdd=function(){n+=1}     function f2(){         console.log(n);
         }     return f2;
    
     } var result=f1();     //等同于return f2();
    
     result(); // 999
    
     nAdd();
    
     result(); // 1000
     nAdd();
    
     result(); // 1000复制代码

    从输出结果就可以看得出来,这个变量 n 就一直保存在内存中,那么,为什么会这样子呢,我们现在就来逐步地分析代码

    ① 首先 f1() 作为 f2() 的父函数,根据作用域链的规则, nAdd() 方法以及 f2() 方法中可以正常访问到 n 的值

    f2() 被赋予了一个全局变量,可能这里大家就会开始产生疑惑了,这个 f2() 不是好好地定义在了 f1() 函数中吗,这不是扯淡吗,那么,先看下面的这句 var result=f1(); ,这个 result 很明显是被赋予了一个全局变量,这应该是没有任何争议的,那么,接着来看这个 f1() ,可以看到最后,是一句 return f2; ,看到这里,想必大家也已经想明白了,这个 f2() 被赋予了一个全局变量

    ③ 已经明白了上面的这一点以后,根据上面垃圾回收机制所提及到的标记清除法,这个 f2() 始终是可以被根对象 Window 访问到的,所以 f2 将始终存在于内存之中,而 f2 是依赖于 f1 ,因此 f1 也将始终存在于内存当中,那么, n 的值也就自然始终存在于内存当中啦

    ④ 还有一点需要注意的就是为什么我们可以直接执行 nAdd() ,这是因为在 nAdd() 的前面没有使用 var ,因此 nAdd() 是一个全局函数而不是局部函数

    所以,闭包的变量会常驻内存,滥用闭包容易造成内存泄漏,特别是在 IE 浏览器下,2020年了,应该没人使用 IE 了吧(小声bb),解决办法就是在退出函数之前,将不使用的局部变量全部删除,这也是上面讲了垃圾回收机制 => 内存泄漏,再讲到闭包的原因,我会尽量将有关联性的知识点一起讲了,也方便大家学习和加深印象。

系列目录

相关免费学习推荐:javascript(视频)

以上是一张纸搞懂JS系列(3)之垃圾回收机制,内存泄漏,闭包的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:juejin。如有侵权,请联系admin@php.cn删除
Windows 上的暗黑破坏神 4 内存泄漏问题:如何修复Windows 上的暗黑破坏神 4 内存泄漏问题:如何修复Apr 13, 2023 pm 09:34 PM

Windows 上的暗黑破坏神 4 内存泄漏问题:13 种修复方法暗黑破坏神 4 的内存泄漏可能由多种问题引起。该游戏目前仍处于开发阶段,因此可以预料到此类问题。内存泄漏的主要原因似乎是暗黑破坏神 4 中的纹理质量设置。我们建议您从下面提到的第一个修复开始,然后浏览列表直到您设法解决问题。让我们开始吧。方法 1:将纹理质量设置为中或低“高”纹理质量似乎是暗黑破坏神 4 内存泄漏的主要原因。这似乎是一个意想不到的错误,因为拥有高端 GPU 和工作站的用户也报告说这是一个潜在的修复方法。前往您的暗黑

C#中常见的内存管理问题及解决方法C#中常见的内存管理问题及解决方法Oct 11, 2023 am 09:21 AM

C#中常见的内存管理问题及解决方法,需要具体代码示例在C#开发中,内存管理是一个重要的问题,不正确的内存管理可能会导致内存泄漏和性能问题。本文将向读者介绍C#中常见的内存管理问题,并提供解决方法,并给出具体的代码示例。希望能帮助读者更好地理解和掌握内存管理技术。垃圾回收器不及时释放资源C#中的垃圾回收器(GarbageCollector)负责自动释放不再使

golang内存泄漏原因有哪些golang内存泄漏原因有哪些Jan 10, 2023 pm 05:45 PM

泄漏原因有:1、time.After()的使用,每次time.After(duration x)会产生NewTimer(),在duration x到期之前,新创建的timer不会被GC,到期之后才会GC;2、time.NewTicker资源未及时释放;3、select阻塞;4、channel阻塞;5、申请过多的goroutine、goroutine阻塞;6、slice引起的等。

闭包引起的内存泄漏有哪些闭包引起的内存泄漏有哪些Nov 22, 2023 pm 02:51 PM

闭包引起的内存泄漏有:1、无限循环和递归调用;2、闭包内部引用了全局变量;3、闭包内部引用了不可清理的对象。详细介绍:1、无限循环和递归调用,当一个闭包在内部引用外部的变量,并且这个闭包又被外部的代码反复调用时,就可能导致内存泄漏,这是因为每次调用都会在内存中创建一个新的作用域,并且这个作用域不会被垃圾回收机制清理;2、闭包内部引用了全局变量,如果在闭包内部引用了全局变量等等。

解决Go语言开发中的内存泄漏定位问题的方法解决Go语言开发中的内存泄漏定位问题的方法Jul 01, 2023 pm 12:33 PM

解决Go语言开发中的内存泄漏定位问题的方法内存泄漏是程序开发中常见的问题之一。在Go语言开发中,由于其自动垃圾回收机制的存在,内存泄漏问题相对其他语言来说可能较少。然而,当我们面对大型复杂的应用程序时,仍然可能会出现内存泄漏的情况。本文将介绍一些在Go语言开发中定位和解决内存泄漏问题的常用方法。首先,我们需要了解什么是内存泄漏。简单来说,内存泄漏指的是程序中

Python开发注意事项:避免常见的内存泄漏问题Python开发注意事项:避免常见的内存泄漏问题Nov 22, 2023 pm 01:43 PM

Python作为一种高级编程语言,具有易学易用和开发效率高等优点,在开发人员中越来越受欢迎。但是,由于其垃圾回收机制的实现方式,Python在处理大量内存时,容易出现内存泄漏问题。本文将从常见内存泄漏问题、引起问题的原因以及避免内存泄漏的方法三个方面来介绍Python开发过程中需要注意的事项。一、常见内存泄漏问题内存泄漏是指程序在运行中分配的内存空间无法释放

Python开发中遇到的内存管理问题及解决方案Python开发中遇到的内存管理问题及解决方案Oct 09, 2023 pm 09:36 PM

Python开发中遇到的内存管理问题及解决方案摘要:在Python开发过程中,内存管理是一个重要的问题。本文将讨论一些常见的内存管理问题,并介绍相应的解决方案,包括引用计数、垃圾回收机制、内存分配、内存泄漏等。并提供了具体的代码示例来帮助读者更好地理解和应对这些问题。引用计数Python使用引用计数来管理内存。引用计数是一种简单而高效的内存管理方式,它记录每

使用上下文装饰器调试Pytorch的内存泄漏问题使用上下文装饰器调试Pytorch的内存泄漏问题Apr 10, 2023 am 11:31 AM

装饰器是 python 上下文管理器的特定实现。本片文章将通过一个pytorch GPU 调试的示例来说明如何使用它们。虽然它可能不适用于所有情况,但我它们却是非常有用。调试内存泄漏问题有很多方法可以调试内存泄漏。本文将展示一种识别代码中有问题的行的有用方法。该方法可以有助于以简洁的方式找到具体的位置。逐行手动调试如果遇到问题,一种经典的且常用的方法是使用调试器逐行检查,比如下面的例子:在搜索引擎查找有关如何计算 pytorch 中所有张量总数的代码片段,比如:tensor-counter-s

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。