목차
예기치 않은 전역 변수" >예기치 않은 전역 변수
해결책: " >해결책:
console.log" >console.log
예------>demos/log.html" >예------>demos/log.html
closures(闭包)" >closures(闭包)
实例------>demos/closures.html" >实例------>demos/closures.html
DOM泄露" >DOM泄露
实例------>demos/dom.html" >实例------>demos/dom.html
小试牛刀------>demos/dom_practice.html" >小试牛刀------>demos/dom_practice.html
timers" >timers
웹 프론트엔드 JS 튜토리얼 일반적인 JavaScript 메모리 누수

일반적인 JavaScript 메모리 누수

Dec 05, 2017 pm 04:31 PM
javascript js 양보하다

메모리 누수란 무엇인가요

메모리 누수는 프로그램의 부주의나 오류로 인해 더 이상 사용되지 않는 메모리를 해제하지 못하는 것을 말합니다. 메모리 누수는 메모리가 물리적으로 사라지는 것을 의미하는 것이 아니라, 애플리케이션이 특정 메모리 세그먼트를 할당한 후 설계 오류로 인해 해당 메모리 세그먼트가 해제되기 전에 해당 메모리 세그먼트에 대한 제어권을 상실하여 오류가 발생하는 것을 의미합니다. 기억력 낭비.
메모리 누수는 일반적으로 프로그램 소스 코드에 액세스할 수 있는 프로그래머만 분석할 수 있습니다. 그러나 엄밀히 말하면 정확하지는 않더라도 메모리 사용량이 원치 않게 증가하는 것을 메모리 누수로 설명하는 데 익숙한 사람이 꽤 있습니다.
————wikipedia

예기치 않은 전역 변수

JavaScript가 선언되지 않은 변수를 처리하는 방법: 전역 개체의 변수에 대한 참조를 만듭니다(즉, 변수가 아닌 전역 개체의 속성입니다. 삭제를 통해 삭제할 수 있습니다.) 브라우저에 있는 경우 전역 개체는 창 개체입니다.

선언되지 않은 변수가 많은 양의 데이터를 캐시하는 경우 창을 닫거나 페이지를 새로 고칠 때만 데이터를 해제할 수 있습니다. 이로 인해 예기치 않은 메모리 누수가 발생할 수 있습니다.

<span style="font-size: 14px;">function foo(arg) {<br>    bar = "this is a hidden global variable with a large of data";<br>}<br></span>
로그인 후 복사

는 다음과 같습니다.

<span style="font-size: 14px;">function foo(arg) {<br>    window.bar = "this is an explicit global variable with a large of data";<br>}<br></span>
로그인 후 복사

또한 다음을 통해 예상치 못한 전역 변수를 만듭니다.

<span style="font-size: 14px;">function foo() {<br>    this.variable = "potential accidental global";<br>}<br><br>// 当在全局作用域中调用foo函数,此时this指向的是全局对象(window),而不是'undefined'<br>foo();<br></span>
로그인 후 복사

해결책:

엄격 모드를 켜려면 JavaScript 파일에 'use strict'를 추가하세요. , 위의 문제를 효과적으로 피할 수 있습니다.

<span style="font-size: 14px;">function foo(arg) {<br>    "use strict" // 在foo函数作用域内开启严格模式<br>    bar = "this is an explicit global variable with a large of data";// 报错:因为bar还没有被声明<br>}<br></span>
로그인 후 복사

함수에서 전역 변수를 사용해야 하는 경우 다음 코드와 같이 창에서 이를 명시적으로 선언할 수 있습니다.

<span style="font-size: 14px;">function foo(arg) {<br>    window.bar = "this is a explicit global variable with a large of data";<br>}<br></span>
로그인 후 복사

가독성이 높을 뿐만 아니라 향후 유지 관리에도 편리합니다

전역 변수라고 하면 대용량 데이터를 임시로 저장하는 데 사용되는 전역 변수에 주의가 필요합니다. 반드시 null로 설정하거나 데이터 처리 후 재할당해야 합니다. 일반적으로 캐시는 성능 최적화를 위해 사용되며, 캐시 크기에 상한선을 설정하는 것이 가장 좋습니다. 캐시는 회수할 수 없으므로 캐시가 높을수록 메모리 소비도 많아집니다.

console.log

console.log: 개발 중 디버깅 및 분석에 자주 사용되는 웹 개발 콘솔에 메시지를 인쇄합니다. 때로는 개발 중에 일부 개체 정보를 인쇄해야 하지만 게시할 때 console.log 문을 제거하는 것을 잊었습니다. 이로 인해 메모리 누수가 발생할 수 있습니다.

console.log에 전달된 개체는 가비지 수집될 수 없습니다. ♻️ 코드 실행 후 개체 정보를 개발 도구에서 확인해야 하기 때문입니다. 따라서 프로덕션 환경에서는 어떤 개체도 console.log에 기록하지 않는 것이 가장 좋습니다.

예------>demos/log.html

<span style="font-size: 14px;"><!DOCTYPE html><br><html lang="en"><br><br><head><br>  <meta charset="UTF-8"><br>  <meta name="viewport" content="width=device-width, initial-scale=1.0"><br>  <meta http-equiv="X-UA-Compatible" content="ie=edge"><br>  <title>Leaker</title><br></head><br><br><body><br>  <input type="button" value="click"><br>  <script><br>    !function () {<br>      function Leaker() {<br>        this.init();<br>      };<br>      Leaker.prototype = {<br>        init: function () {<br>          this.name = (Array(100000)).join('*');<br>          console.log("Leaking an object %o: %o", (new Date()), this);// this对象不能被回收<br>        },<br><br>        destroy: function () {<br>          // do something....<br>        }<br>      };<br>      document.querySelector('input').addEventListener('click', function () {<br>        new Leaker();<br>      }, false);<br>    }()<br>  </script><br></body><br><br></html><br></span>
로그인 후 복사

여기에 Chrome의 Devtools–>성능을 결합하여 몇 가지 분석을 수행합니다.

⚠️참고 : 브라우저 플러그인이 분석 결과에 영향을 미치지 않도록 숨겨진 창에서 분석 작업을 수행하는 것이 가장 좋습니다

  1. [성능] 항목의 기록을 활성화

  2. CG를 한 번 실행하고 기준선 참조선

  3. 버튼을 세 번 연속 클릭 [클릭]하면 세 개의 Leaker 개체가 생성됩니다

  4. CG 한 번 실행

  5. 녹화 중지

일반적인 JavaScript 메모리 누수

그것 [JS Heap] 라인이 최종 레벨로 떨어지지 않은 것을 볼 수 있습니다. 기준선 참조 라인 위치에는 분명히 회수되지 않은 메모리가 있습니다. 코드를 다음과 같이 수정하면

<span style="font-size: 14px;">    !function () {<br>      function Leaker() {<br>        this.init();<br>      };<br>      Leaker.prototype = {<br>        init: function () {<br>          this.name = (Array(100000)).join('*');<br>        },<br><br>        destroy: function () {<br>          // do something....<br>        }<br>      };<br>      document.querySelector('input').addEventListener('click', function () {<br>        new Leaker();<br>      }, false);<br>    }()<br></span>
로그인 후 복사

console.log("Leaking an object %o: %o", (new Date()), this); 위 단계를 반복하면 분석 결과는 다음과 같습니다.

일반적인 JavaScript 메모리 누수

비교 분석 결과에서 console.log로 출력된 객체는 가비지 컬렉터에서 재활용되지 않음을 알 수 있습니다. 따라서 페이지의 큰 개체는 console.log에 기록하지 않는 것이 가장 좋습니다. 이는 특히 프로덕션 환경에서 페이지의 전체 성능에 영향을 미칠 수 있기 때문입니다. console.log 외에도 console.dir, console.error, console.warn 등과 같은 유사한 문제도 있습니다. 이러한 세부 사항에는 특별한 주의가 필요합니다.

closures(闭包)

当一个函数A返回一个内联函数B,即使函数A执行完,函数B也能访问函数A作用域内的变量,这就是一个闭包——————本质上闭包是将函数内部和外部连接起来的一座桥梁。

<span style="font-size: 14px;">function foo(message) {<br>    function closure() {<br>        console.log(message)<br>    };<br>    return closure;<br>}<br><br>// 使用<br>var bar = foo("hello closure!");<br>bar()// 返回 'hello closure!'<br></span>
로그인 후 복사

在函数foo内创建的函数closure对象是不能被回收掉的,因为它被全局变量bar引用,处于一直可访问状态。通过执行bar()可以打印出hello closure!。如果想释放掉可以将bar = null即可。

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多。

实例------>demos/closures.html

<span style="font-size: 14px;"><!DOCTYPE html><br><html lang="en"><br><br><head><br>  <meta charset="UTF-8"><br>  <meta name="viewport" content="width=device-width, initial-scale=1.0"><br>  <meta http-equiv="X-UA-Compatible" content="ie=edge"><br>  <title>Closure</title><br></head><br><br><body><br>  <p>不断单击【click】按钮</p><br>  <button id="click_button">Click</button><br>  <script><br>    function f() {<br>      var str = Array(10000).join('#');<br>      var foo = {<br>        name: 'foo'<br>      }<br>      function unused() {<br>        var message = 'it is only a test message';<br>        str = 'unused: ' + str;<br>      }<br>      function getData() {<br>        return 'data';<br>      }<br>      return getData;<br>    }<br><br>    var list = [];<br>    <br>    document.querySelector('#click_button').addEventListener('click', function () {<br>      list.push(f());<br>    }, false);<br>  </script><br></body><br><br></html><br></span>
로그인 후 복사

这里结合Chrome的Devtools->Memory工具进行分析,操作步骤如下:

⚠️注:最好在隐藏窗口中进行分析工作,避免浏览器插件影响分析结果

  1. 选中【Record allocation timeline】选项

  2. 执行一次CG

  3. 单击【start】按钮开始记录堆分析

  4. 连续单击【click】按钮十多次

  5. 停止记录堆分析

일반적인 JavaScript 메모리 누수

上图中蓝色柱形条表示随着时间新分配的内存。选中其中某条蓝色柱形条,过滤出对应新分配的对象:

일반적인 JavaScript 메모리 누수

查看对象的详细信息:

일반적인 JavaScript 메모리 누수

从图可知,在返回的闭包作用链(Scopes)中携带有它所在函数的作用域,作用域中还包含一个str字段。而str字段并没有在返回getData()中使用过。为什么会存在在作用域中,按理应该被GC回收掉, why

原因是在相同作用域内创建的多个内部函数对象是共享同一个变量对象(variable object)。如果创建的内部函数没有被其他对象引用,不管内部函数是否引用外部函数的变量和函数,在外部函数执行完,对应变量对象便会被销毁。反之,如果内部函数中存在有对外部函数变量或函数的访问(可以不是被引用的内部函数),并且存在某个或多个内部函数被其他对象引用,那么就会形成闭包,外部函数的变量对象就会存在于闭包函数的作用域链中。这样确保了闭包函数有权访问外部函数的所有变量和函数。了解了问题产生的原因,便可以对症下药了。对代码做如下修改:

<span style="font-size: 14px;">    function f() {<br>      var str = Array(10000).join('#');<br>      var foo = {<br>        name: 'foo'<br>      }<br>      function unused() {<br>        var message = 'it is only a test message';<br>        // str = 'unused: ' + str; //删除该条语句<br>      }<br>      function getData() {<br>        return 'data';<br>      }<br>      return getData;<br>    }<br><br>    var list = [];<br>    <br>    document.querySelector('#click_button').addEventListener('click', function () {<br>      list.push(f());<br>    }, false);<br></span>
로그인 후 복사

getData()和unused()内部函数共享f函数对应的变量对象,因为unused()内部函数访问了f作用域内str变量,所以str字段存在于f变量对象中。加上getData()内部函数被返回,被其他对象引用,形成了闭包,因此对应的f变量对象存在于闭包函数的作用域链中。这里只要将函数unused中str = 'unused: ' + str;语句删除便可解决问题。

일반적인 JavaScript 메모리 누수

查看一下闭包信息:

일반적인 JavaScript 메모리 누수

DOM泄露

在JavaScript中,DOM操作是非常耗时的。因为JavaScript/ECMAScript引擎独立于渲染引擎,而DOM是位于渲染引擎,相互访问需要消耗一定的资源。如Chrome浏览器中DOM位于WebCore,而JavaScript/ECMAScript位于V8中。假如将JavaScript/ECMAScript、DOM分别想象成两座孤岛,两岛之间通过一座收费桥连接,过桥需要交纳一定“过桥费”。JavaScript/ECMAScript每次访问DOM时,都需要交纳“过桥费”。因此访问DOM次数越多,费用越高,页面性能就会受到很大影响。了解更多ℹ️

일반적인 JavaScript 메모리 누수

为了减少DOM访问次数,一般情况下,当需要多次访问同一个DOM方法或属性时,会将DOM引用缓存到一个局部变量中。但如果在执行某些删除、更新操作后,可能会忘记释放掉代码中对应的DOM引用,这样会造成DOM内存泄露。

实例------>demos/dom.html

<span style="font-size: 14px;"><!DOCTYPE html><br><html lang="en"><br><head><br>  <meta charset="UTF-8"><br>  <meta name="viewport" content="width=device-width, initial-scale=1.0"><br>  <meta http-equiv="X-UA-Compatible" content="ie=edge"><br>  <title>Dom-Leakage</title><br></head><br><body><br>  <input type="button" value="remove" class="remove"><br>  <input type="button" value="add" class="add"><br><br>  <p class="container"><br>    <pre class="wrapper">

  


  

핫 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를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

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

WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 Dec 17, 2023 pm 02:54 PM

WebSocket 및 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 소개: 지속적인 기술 개발로 음성 인식 기술은 인공 지능 분야의 중요한 부분이 되었습니다. WebSocket과 JavaScript를 기반으로 한 온라인 음성 인식 시스템은 낮은 대기 시간, 실시간, 크로스 플랫폼이라는 특징을 갖고 있으며 널리 사용되는 솔루션이 되었습니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법을 소개합니다.

주식 분석을 위한 필수 도구: PHP 및 JS를 사용하여 캔들 차트를 그리는 단계를 알아보세요. 주식 분석을 위한 필수 도구: PHP 및 JS를 사용하여 캔들 차트를 그리는 단계를 알아보세요. Dec 17, 2023 pm 06:55 PM

주식 분석을 위한 필수 도구: PHP 및 JS에서 캔들 차트를 그리는 단계를 배우십시오. 인터넷과 기술의 급속한 발전으로 주식 거래는 많은 투자자에게 중요한 방법 중 하나가 되었습니다. 주식분석은 투자자의 의사결정에 있어 중요한 부분이며 캔들차트는 기술적 분석에 널리 사용됩니다. PHP와 JS를 사용하여 캔들 차트를 그리는 방법을 배우면 투자자가 더 나은 결정을 내리는 데 도움이 되는 보다 직관적인 정보를 얻을 수 있습니다. 캔들스틱 차트는 주가를 캔들스틱 형태로 표시하는 기술 차트입니다. 주가를 보여주네요

권장 사항: 우수한 JS 오픈 소스 얼굴 감지 및 인식 프로젝트 권장 사항: 우수한 JS 오픈 소스 얼굴 감지 및 인식 프로젝트 Apr 03, 2024 am 11:55 AM

얼굴 검출 및 인식 기술은 이미 상대적으로 성숙하고 널리 사용되는 기술입니다. 현재 가장 널리 사용되는 인터넷 응용 언어는 JS입니다. 웹 프런트엔드에서 얼굴 감지 및 인식을 구현하는 것은 백엔드 얼굴 인식에 비해 장점과 단점이 있습니다. 장점에는 네트워크 상호 작용 및 실시간 인식이 줄어 사용자 대기 시간이 크게 단축되고 사용자 경험이 향상된다는 단점이 있습니다. 모델 크기에 따라 제한되고 정확도도 제한됩니다. js를 사용하여 웹에서 얼굴 인식을 구현하는 방법은 무엇입니까? 웹에서 얼굴 인식을 구현하려면 JavaScript, HTML, CSS, WebRTC 등 관련 프로그래밍 언어 및 기술에 익숙해야 합니다. 동시에 관련 컴퓨터 비전 및 인공지능 기술도 마스터해야 합니다. 웹 측면의 디자인으로 인해 주목할 가치가 있습니다.

WebSocket 및 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 WebSocket 및 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 Dec 17, 2023 pm 05:30 PM

WebSocket과 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 서론: 인터넷 기술의 급속한 발전과 함께 실시간 모니터링 시스템이 다양한 분야에서 널리 활용되고 있다. 실시간 모니터링을 구현하는 핵심 기술 중 하나는 WebSocket과 JavaScript의 조합입니다. 이 기사에서는 실시간 모니터링 시스템에서 WebSocket 및 JavaScript의 적용을 소개하고 코드 예제를 제공하며 구현 원칙을 자세히 설명합니다. 1. 웹소켓 기술

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 Dec 17, 2023 pm 12:09 PM

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 소개: 인터넷의 대중화와 기술의 발전으로 점점 더 많은 레스토랑에서 온라인 주문 서비스를 제공하기 시작했습니다. 실시간 온라인 주문 시스템을 구현하기 위해 JavaScript 및 WebSocket 기술을 사용할 수 있습니다. WebSocket은 TCP 프로토콜을 기반으로 하는 전이중 통신 프로토콜로 클라이언트와 서버 간의 실시간 양방향 통신을 실현할 수 있습니다. 실시간 온라인 주문 시스템에서는 사용자가 요리를 선택하고 주문을 하면

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 Dec 17, 2023 am 09:39 AM

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 오늘날의 디지털 시대에는 점점 더 많은 기업과 서비스에서 온라인 예약 기능을 제공해야 합니다. 효율적인 실시간 온라인 예약 시스템을 구현하는 것이 중요합니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. WebSocket이란 무엇입니까? WebSocket은 단일 TCP 연결의 전이중 방식입니다.

PHP 및 JS 개발 팁: 주식 캔들 차트 그리기 방법 익히기 PHP 및 JS 개발 팁: 주식 캔들 차트 그리기 방법 익히기 Dec 18, 2023 pm 03:39 PM

인터넷 금융의 급속한 발전으로 인해 주식 투자는 점점 더 많은 사람들의 선택이 되었습니다. 주식 거래에서 캔들 차트는 주가의 변화 추세를 보여주고 투자자가 보다 정확한 결정을 내리는 데 도움이 되는 일반적으로 사용되는 기술적 분석 방법입니다. 이 기사에서는 PHP와 JS의 개발 기술을 소개하고 독자가 주식 캔들 차트를 그리는 방법을 이해하도록 유도하며 구체적인 코드 예제를 제공합니다. 1. 주식 캔들 차트의 이해 주식 캔들 차트를 그리는 방법을 소개하기 전에 먼저 캔들 차트가 무엇인지부터 이해해야 합니다. 캔들스틱 차트는 일본인이 개발했습니다.

JavaScript와 WebSocket: 효율적인 실시간 일기예보 시스템 구축 JavaScript와 WebSocket: 효율적인 실시간 일기예보 시스템 구축 Dec 17, 2023 pm 05:13 PM

JavaScript 및 WebSocket: 효율적인 실시간 일기 예보 시스템 구축 소개: 오늘날 일기 예보의 정확성은 일상 생활과 의사 결정에 매우 중요합니다. 기술이 발전함에 따라 우리는 날씨 데이터를 실시간으로 획득함으로써 보다 정확하고 신뢰할 수 있는 일기예보를 제공할 수 있습니다. 이 기사에서는 JavaScript 및 WebSocket 기술을 사용하여 효율적인 실시간 일기 예보 시스템을 구축하는 방법을 알아봅니다. 이 문서에서는 특정 코드 예제를 통해 구현 프로세스를 보여줍니다. 우리

See all articles