찾다
웹 프론트엔드JS 튜토리얼JS 시리즈(3)의 가비지 수집 메커니즘, 메모리 누수, 클로저를 종이 한 장으로 이해하기

javascript 칼럼에서는 가비지 수집 메커니즘, 메모리 누수 및 클로저 내용을 모두에게 소개합니다.

JS 시리즈(3)의 가비지 수집 메커니즘, 메모리 누수, 클로저를 종이 한 장으로 이해하기

Written at the front: 이것은 주로 프레임워크가 만연한 시대에 javascript 칼럼에 쓰기 시작하는 시리즈입니다. 업무용, 인터뷰용, 기술 발전용으로 프레임워크를 사용하지만, JS의 기본 지식은 금상첨화이며 꼭 배워야 할 지식이기도 합니다. 자동차를 운전하는 사람은 자동차에 대해 많이 알 필요는 없지만 자동차의 일반적인 기능만 익히면 됩니다. . 하지만 자동차를 안다면 운전을 더 잘할 수 있습니다. 물론, 기사는 단지 하나의 지식 포인트에 대해서만 이야기하는 것이 아닙니다. 일반적으로 관련된 지식 포인트가 시리즈로 연결되어 자신의 학습을 기록하면서 자신의 학습을 공유하고 서로 격려하게 됩니다! 가능하시다면 좋아요도 부탁드려요, 여러분의 좋아요 덕분에 저도 업데이트하는데 더 힘이 됩니다!

개요

  • 식사 시간: 6~12분
  • 난이도: 쉬움, 뛰지 말고 다 읽을 때까지 기다리세요

쓰레기 수집 메커니즘

이전 블로그에서는 주로 메모리(스택 메모리 및 힙 메모리, 딥 카피 및 얕은 카피)는 물론 사용 후에는 사용하지 않은 메모리를 반환해야 합니다. 마치 휴대폰에서 사용하지 않는 소프트웨어를 백그라운드에서 삭제하는 것과 마찬가지로 실행 속도를 향상시킬 수 있습니다. 그렇지 않으면 더 많이 사용할수록 조만간 정체될 것입니다. JS도 마찬가지입니다. 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가끔 JSGarbage Collector는 공원을 순찰하는 경비원처럼 변수를 "순찰"하여 관련 없는 사람들을 빠르게 떠나게 합니다. 변수가 더 이상 필요하지 않으면 변수가 차지하는 메모리 공간을 해제합니다. 이 프로세스를 garbage collection

  • JS의 가비지 수집 알고리즘은 두 가지 유형으로 나누어집니다. 및 마크 지우기

    참조 카운팅 참조 카운팅은 가장 기본적인 가비지 수집 알고리즘이며 최신 브라우저에서 제거되었습니다. 참조 카운팅 방법을 배우기 전에 먼저 reference라는 개념을 알아야 합니다. 현재 변수가 가리키는 메모리 주소에 대한 설명이라고 생각하면 됩니다. JS 참조 데이터 유형 먼저 코드 줄을 살펴보겠습니다.
    function changeName(){    var obj1={};  var obj2={};
      
      obj1.target=obj2;
      obj2.target=obj1;
      obj1.age=15;  console.log(obj1.target);  console.log(obj2.target);
    }
    
    changeName();复制代码
    obj에 값을 할당하면 실제로 참조 개수가 1인 변수를 가리키는 reference
      가 생성됩니다. ,
    • 참조 카운트 메커니즘에 따라 메모리의 각 값은 참조 카운트에 해당합니다

      그리고 objnull에 할당하면 이 변수는 쓸모없는 메모리 조각, 그러면 이때 obj의 참조 횟수는 0이 되고 가비지 컬렉터에 의해 재활용됩니다. 즉, obj가 차지하는 메모리 공간입니다. 가 출시됩니다

    • 함수 범위의 수명주기는 매우 짧습니다. 함수가 실행된 후 내부 변수는 기본적으로 쓸모없는 변수입니다. 이를 지우지 않으면 메모리 쓰레기가 됩니다. 해제되지 않고 여전히 사용 중입니다. 원래 메모리를 버리지 않으면
    • 메모리 누수

      가 발생하기 쉽습니다. 먼저 코드 일부와 실행 결과를 살펴보겠습니다.

       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复制代码
      JS 시리즈(3)의 가비지 수집 메커니즘, 메모리 누수, 클로저를 종이 한 장으로 이해하기
      obj1.targetobj2.target이 서로를 참조하는 것을 볼 수 있습니다. obj1.age일 때 >가 변경되면 obj1.target.ageobj2.target.age도 동시에 영향을 받습니다. 실행 시 obj1obj2는 여전히 살아 있습니다. obj1.targetobj2.target의 참조 카운트 때문입니다. > 실행 후에도 여전히 1

      , 분명히 함수가 실행되었지만 이런 쓰레기가 여전히 존재합니다. 이러한 함수가 너무 많으면 🎜메모리 누수🎜가 불가피합니다🎜🎜🎜🎜마크 및 지우기 방법🎜🎜 위의 참조 카운팅 방법의 단점은 이미 명백합니다. 그러면 지금 우리가 말하는 마크 앤 클리어 방법에는 그러한 문제가 없습니다. 판단 기준은 객체 🎜가 도달 가능 🎜인지 확인하는 것이므로 주로 🎜 표시 단계 🎜와 🎜 삭제 단계 🎜의 두 단계로 나뉩니다. 🎜🎜🎜🎜 표시 단계 🎜🎜 가비지 수집기는 다음에서 시작됩니다. 루트 객체(Window 객체) 및 도달 가능한 모든 객체를 검색하는 것이 소위 🎜reachable🎜🎜🎜🎜🎜제거 단계입니다. 스캔하는 동안 루트 개체가 건드릴 수 없는 개체(🎜unreachable🎜)는 불필요한 개체로 간주되어 가비지로 삭제됩니다🎜

    现在再来看下上面的代码

    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 和工作站的用户也报告说这是一个潜在的修复方法。前往您的暗黑

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引起的等。

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

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

闭包引起的内存泄漏有哪些闭包引起的内存泄漏有哪些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开发中遇到的内存管理问题及解决方案Oct 09, 2023 pm 09:36 PM

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

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

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

内存溢出和内存泄漏有什么区别内存溢出和内存泄漏有什么区别Aug 21, 2023 pm 03:14 PM

内存溢出和内存泄漏的区别在于内存溢出是指程序在申请内存时无法获得所需的内存空间,而内存泄漏是指程序在运行过程中分配的内存无法被正常释放,内存溢出通常是由于程序需要的内存超过了可用的内存限制,或者递归调用导致栈空间耗尽,或者内存泄漏导致的,而内存泄漏则是由于程序中存在未释放的动态分配内存、对象引用未被正确释放或循环引用导致的。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경