目次
概要
に到達できるかどうかなので、主に
内存泄漏
闭包
定义与特性
系列目录
一张纸懂JS系列(1)之编译原理,作用域,作用域链,变量提升,暂时性死区" >一张纸懂JS系列(1)之编译原理,作用域,作用域链,变量提升,暂时性死区
一张纸搞懂JS系列(2)之JS内存生命周期,栈内存与堆内存,深浅拷贝" >一张纸搞懂JS系列(2)之JS内存生命周期,栈内存与堆内存,深浅拷贝
一张纸搞懂JS系列(3)之垃圾回收机制,内存泄漏,闭包
ホームページ ウェブフロントエンド jsチュートリアル JSシリーズのガベージコレクションの仕組み、メモリリーク、クロージャが紙1枚でわかる(3)

JSシリーズのガベージコレクションの仕組み、メモリリーク、クロージャが紙1枚でわかる(3)

Sep 30, 2020 pm 04:38 PM
メモリーリーク ガベージコレクションの仕組み 閉鎖

javascriptこのコラムでは、ガベージ コレクションのメカニズム、メモリ リーク、クロージャの内容について紹介します。ファストエンド ベンチを見てみましょう。

JSシリーズのガベージコレクションの仕組み、メモリリーク、クロージャが紙1枚でわかる(3)

先頭に書く: これは、javascript 列で主に書き始めようとしているシリーズです。時代の中で、仕事や面接、技術向上のためにフレームワークを使っているとはいえ、JSの基礎知識はおまけであり、学ばなければいけない知識でもあります。車を運転するのに車について詳しく知る必要はなく、車の一般的な使い方をマスターするだけで十分です。しかし、車の知識があれば、同様に、より上手に運転することができます。もちろん、記事は一つの知識だけを語るのではなく、関連する知識が連続してつながっていくのが一般的で、自分の学びを記録しながら、自分の学びを共有し、励まし合いましょう!できれば、「いいね」もお願いします。あなたの「いいね」が更新の励みにもなります。

概要

  • 食事時間: 6〜12分
  • 難易度: 簡単、走らずに、帰る前に見てください。
##ガベージコレクションの仕組み

前回のブログでは主にメモリの割り当てと使い方(スタックメモリとヒープメモリ、ディープコピーとシャローコピー)について説明しました。未使用のメモリは、携帯電話上の未使用のソフトウェアをバックグラウンドから消去するようなもので、携帯電話の動作速度を向上させることができます。そうしないと、メモリの使用量が増えると、遅かれ早かれスタックしてしまいます。

JS についても同様です。

JSガベージ コレクター は、公園の警備パトロールと同じように、変数を「パトロール」し、関係のない人はすぐに立ち去ることができます。変数が不要になった場合、その変数が占有していたメモリ領域を解放します。このプロセスは ガベージ コレクション

JS と呼ばれます。リサイクル アルゴリズム、参照カウント、およびマークのクリア。

  • 参照カウント メソッド

    参照カウント メソッドは、最も基本的なガベージ コレクション アルゴリズムであり、最新のブラウザで使用されています。装備は撤去されました。参照カウント方法を学ぶ前に、まず

    reference という特定の概念を理解する必要があります。これは、現在の変数が指すメモリ アドレスの記述として考えることができ、メモリに似ています。 JS 参照データ型のポインター。概念を理解するために、まずコード行を見てみましょう:

    var obj={name:'jack'};复制代码
    ログイン後にコピー

    値を

    obj に割り当てると、実際には が作成されます。 Reference 変数を指します。参照カウントは 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シリーズのガベージコレクションの仕組み、メモリリーク、クロージャが紙1枚でわかる(3)
    ##obj1.target
    と ## が確認できます。 #obj2.target には相互参照があります。obj1.age が変更されると、obj1.target.ageobj2.target.age が変更されるためです。も同時に影響を受け、参照カウントが一貫していることを示します。 関数が実行されると、obj1

    obj2 はまだ有効です。なぜなら obj1.targetobj2.target の実行が完了しても、参照カウントは 1 のままで、関数が実行されたことは明らかですが、このようなものこのような関数が定義されすぎているため、メモリリークこれも避けられません

    マーククリア方法
  • デメリット上記の参照カウント方法はすでに明らかなので、ここではマーキングのクリア方法について説明します。そのような問題はありません。判定基準はオブジェクト

    に到達できるかどうかなので、主に

    マーキングステージ

    クリアステージ:##の2つのステージに分かれます。 #マーキング フェーズ

    ガベージ コレクターはルート オブジェクト (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シリーズのガベージコレクションの仕組み、メモリリーク、クロージャが紙1枚でわかる(3)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホット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ヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

C++ラムダ式でクロージャを実装するにはどうすればよいですか? C++ラムダ式でクロージャを実装するにはどうすればよいですか? Jun 01, 2024 pm 05:50 PM

C++ ラムダ式は、関数スコープ変数を保存し、関数からアクセスできるようにするクロージャーをサポートしています。構文は [キャプチャリスト](パラメータ)->戻り値の型{関数本体} です。 Capture-list は、キャプチャする変数を定義します。[=] を使用してすべてのローカル変数を値によってキャプチャするか、[&] を使用してすべてのローカル変数を参照によってキャプチャするか、[variable1, variable2,...] を使用して特定の変数をキャプチャできます。ラムダ式はキャプチャされた変数にのみアクセスできますが、元の値を変更することはできません。

C++ 関数におけるクロージャの長所と短所は何ですか? C++ 関数におけるクロージャの長所と短所は何ですか? Apr 25, 2024 pm 01:33 PM

クロージャは、外部関数のスコープ内の変数にアクセスできる入れ子関数です。その利点には、データのカプセル化、状態の保持、および柔軟性が含まれます。デメリットとしては、メモリ消費量、パフォーマンスへの影響、デバッグの複雑さなどが挙げられます。さらに、クロージャは匿名関数を作成し、それをコールバックまたは引数として他の関数に渡すことができます。

Valgrind を使用してメモリ リークを検出するにはどうすればよいですか? Valgrind を使用してメモリ リークを検出するにはどうすればよいですか? Jun 05, 2024 am 11:53 AM

Valgrind は、メモリの割り当てと割り当て解除をシミュレートすることでメモリ リークとエラーを検出します。使用するには、次の手順に従います。 Valgrind をインストールします。公式 Web サイトからオペレーティング システムのバージョンをダウンロードしてインストールします。プログラムをコンパイルする: Valgrind フラグ (gcc-g-omyprogrammyprogram.c-lstdc++ など) を使用してプログラムをコンパイルします。プログラムを分析する: valgrind--leak-check=fullmyprogram コマンドを使用して、コンパイルされたプログラムを分析します。出力を確認します。Valgrind はプログラムの実行後にレポートを生成し、メモリ リークとエラー メッセージを表示します。

Golang の技術的なパフォーマンスの最適化でメモリ リークを回避するにはどうすればよいですか? Golang の技術的なパフォーマンスの最適化でメモリ リークを回避するにはどうすればよいですか? Jun 04, 2024 pm 12:27 PM

メモリ リークは、ファイル、ネットワーク接続、データベース接続などの使用されなくなったリソースを閉じることによって、Go プログラムのメモリを継続的に増加させる可能性があります。弱参照を使用してメモリ リークを防ぎ、強参照されなくなったオブジェクトをガベージ コレクションの対象にします。 go coroutine を使用すると、メモリ リークを避けるために、終了時にコルーチンのスタック メモリが自動的に解放されます。

C++ でのメモリ リークのデバッグ手法 C++ でのメモリ リークのデバッグ手法 Jun 05, 2024 pm 10:19 PM

C++ におけるメモリ リークとは、プログラムがメモリを割り当てたにもかかわらず解放し忘れ、メモリが再利用されなくなることを意味します。デバッグ手法には、デバッガー (Valgrind、GDB など) の使用、アサーションの挿入、メモリ リーク検出ライブラリ (Boost.LeakDetector、MemorySanitizer など) の使用が含まれます。実際のケースを通じてメモリ リークを検出するための Valgrind の使用法を示し、割り当てられたメモリを常に解放する、スマート ポインターを使用する、メモリ管理ライブラリを使用する、定期的なメモリ チェックを実行するなど、メモリ リークを回避するためのベスト プラクティスを提案します。

Java ではクロージャはどのように実装されますか? Java ではクロージャはどのように実装されますか? May 03, 2024 pm 12:48 PM

Java のクロージャを使用すると、外部関数が終了した場合でも、内部関数が外部スコープの変数にアクセスできるようになります。匿名の内部クラスを通じて実装されると、内部クラスは外部クラスへの参照を保持し、外部変数をアクティブに保ちます。クロージャによりコードの柔軟性が向上しますが、匿名の内部クラスによる外部変数への参照により、それらの変数が存続するため、メモリ リークのリスクに注意する必要があります。

テストにおける golang 関数クロージャの役割 テストにおける golang 関数クロージャの役割 Apr 24, 2024 am 08:54 AM

Go 言語の関数クロージャは単体テストで重要な役割を果たします。 値のキャプチャ: クロージャは外側のスコープ内の変数にアクセスできるため、テスト パラメータをキャプチャしてネストされた関数で再利用できます。テスト コードの簡素化: クロージャは値をキャプチャすることで、ループごとにパラメーターを繰り返し設定する必要性を排除し、テスト コードを簡素化します。可読性の向上: クロージャを使用してテスト ロジックを整理し、テスト コードをより明確で読みやすくします。

Valgrind または AddressSanitizer を使用して C++ でメモリ リークを見つけるにはどうすればよいですか? Valgrind または AddressSanitizer を使用して C++ でメモリ リークを見つけるにはどうすればよいですか? Jun 02, 2024 pm 09:23 PM

C++ でメモリ リークを見つけるには、Valgrind と AddressSanitizer を利用できます。 Valgrind はリークを動的に検出し、アドレス、サイズ、呼び出しスタックを表示します。 AddressSanitizer は、メモリ エラーとリークを検出する Clang コンパイラ プラグインです。 ASan リーク チェックを有効にするには、コンパイル時に --leak-check=full オプションを使用します。これにより、プログラムの実行後にリークが報告されます。

See all articles