JavaScript のメモリ管理とクロージャ

JavaScriptの実行原理

次のコードがある場合、JavaScript ではどのように実行されるでしょうか?

1. まずグローバルオブジェクトを初期化します

JS エンジンはコードを実行する前にヒープ メモリにグローバル オブジェクトを作成します。グローバル オブジェクト (GO) はブラウザ環境のウィンドウであり、グローバルはノード環境のグローバル変数であり、ブラウザのウィンドウと同様ですが、コード内で使用することをお勧めします。プロセス オブジェクトは、現在の Node.js プロセスの情報と制御メソッドを提供します。
* オブジェクト内のすべてのスコープがオブジェクトのコンテンツにアクセスできます;
* これには、Date、Array、String、Number、setTimeout、setInterval などが含まれます; * それ
自体を指す window 属性もあります

ここに画像の説明を挿入

2. 各スコープ ブロックの実行コンテキストを作成し、実行コンテキスト スタックに置きます。

js エンジン内に 1 つあり执行上下文栈(Execution Context Stack,简称ECS)、コードを実行するための呼び出しスタックです。
それで、今度は誰を処刑するのでしょうか?実行されるのはグローバル コード ブロックです。
ここに画像の説明を挿入
その中で、これは現在のコンテキストの参照です。

  • グローバル コード ブロックは実行用の実行コンテキストを構築します Global Execution Context(GEC)。関数コード ブロックは実行コンテキストを作成し、グローバル コード ブロックも実行コンテキストを作成します。es6 以降では、ブロック レベルのスコープも実行コンテキストを作成します。のみ実行コンテキストが作成されると、それが使用されます。それを実行コンテキスト スタックに入れて、コードを実行します。
  • 実行コンテキストは、実行のために実行コンテキスト スタックに入れられます。
    実行コンテキスト スタックへの実行コンテキストの内容には、次の 2 つの部分が含まれます。
    • 最初の部分: コードが実行される前に、パーサーを AST に変換するプロセスで、グローバルに定義された変数、関数などが GlobalObject に追加されます。このプロセスは、変数スコープのホイスティングとも呼ばれます。関数宣言は昇格と代入の両方が行われ、その優先順位は var で宣言された変数よりも高いのに対し、var で宣言された変数は昇格されるだけで代入されないことに注意してください。
      ここに画像の説明を挿入
      このうち、foo の出力内容は文字列 abc です。

    • 2 番目の部分: コードの実行中に、実行コンテキストを作成し、変数に値を割り当て、または他の関数を実行します。

JavaScript の実行原則の概要

参考リンク: 実行中のコンテキストスタックの変更のデモ
1. グローバルオブジェクトの初期化
2. 書かれたコードの解析 解析プロセスでは、var 変数と宣言関数を改善する必要があります。
3. コードを実行します。実行中に関数呼び出しが発生した場合は、関数のコンテキストを作成してコンテキスト スタックに置き、各実行コンテキストは VO (変数オブジェクト、変数オブジェクト)、変数、および関数宣言がこの VO オブジェクトに追加されます。

注: 関数が複数層の関数でネストされている場合、初期化時に最初の層のみが解釈され、実行時にその中に関数が存在する場合は、再度説明されて実行されます。-> JavaScript はインタープリタ型言語です边解释边执行代码ブラウザが JavaScript コードを読み込むと、コードを 1 行ずつ解釈し、すぐに実行します。これは、プログラムを実行する前にコードを機械語にコンパイルする必要がある C++ などのコンパイル言語とは異なります。

補足1:VOオブジェクト(Variable Object)について
ここに画像の説明を挿入
補足2:VO、GO(グローバルオブジェクト)、AO(アクティベーションオブジェクト)
ここに画像の説明を挿入

参考リンク:リンク

スコープチェーン

スコープ チェーンは実際には関数内に保存され、コードの定義時に決定され、関数の実行とは何の関係もありません。したがって、変数を見つけるには、コードの順序を見るだけで済みます。書かれており、それがいつ実行されるかには関係がありません。

小技巧: ポイントをブレークすると、現在のデバッグ行のスコープの内容が表示されます。
ここに画像の説明を挿入


メモリ管理

どのようなプログラミング言語であっても、コードを実行する際にはメモリを割り当てる必要がありますが、違いは、メモリを自分で手動で管理する必要があるプログラミング言語と、メモリを手動で管理できるプログラミング言語があることです。メモリ管理を自動的にサポートします。

メモリの管理にどのような方法が使用されるかに関係なく、メモリ管理には次のライフサイクルがあります。

  • 最初のステップ: 必要なメモリを割り当てて適用します (アプリケーション)。
  • 2 番目のステップ: 割り当てられたメモリを使用します (オブジェクトなどのいくつかのものを保存します)。
  • ステップ 3: 使用しないときは解放します。

一般的な GC アルゴリズム:

参考リンク:リンク

  1. 参照カウント
  2. マーク削除 (到達可能性アルゴリズム) - 現在最も使用されており、V8 もこれを使用します
    ここに画像の説明を挿入

null に設定して参照関係を削除します

閉鎖

参考リンク:閉店

コンピューターサイエンスにおけるクロージャの定義は、クロージャが実際には機能と関連する環境から構成される構造であるということです。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/yexudengzhidao/article/details/131865834