JavaScript の実行コンテキストとコールスタックの詳細な説明

JavaScript の実行コンテキストとコールスタックの詳細な説明

1. 実行コンテキストとは何か

コードは特定の環境で実行されます。これを実行環境または実行コンテキストと呼びます。さまざまな実行環境に応じて、次の 3 つのカテゴリに分類できます。

グローバル実行環境: コードが最初に実行されるときのデフォルトの環境

関数実行環境: 実行フローが関数本体に入るたびに

eval実行環境: eval関数内のテキストが実行されると

2. 実行コンテキスト スタックとは何ですか?

これは「スタック」であるため、「スタック」の特性、つまり先入後出のデータ構造に準拠している必要があります。コードの一部を見てみましょう:

関数cat(a){
    もし(a<0){
        false を返します。
    }
    console.log('スタックにプッシュ:'+a);
    猫(a-1);
    console.log('ポップアウト:'+a);
}
猫(3);
// スタックにプッシュ: 3
// スタックにプッシュ: 2
// スタックにプッシュ: 1
// スタックにプッシュ: 0
// スタックをポップ: 0
// ポップ: 1
// ポップ: 2
// ポップ: 3

上記のコードの実行プロセスを分析してみましょう。

① ブラウザがロードされると、プログラムはグローバル実行コンテキストに入り、それをスタックにプッシュします(最初に入るもの、つまり最下層)。この実行コンテキストの下には関数 cat が 1 つだけあり、cat call、パラメータ 3 です。

② プログラムはcat関数に入り、つまり関数の実行コンテキストに入り、それをスタックにプッシュします(2番目に入るもの、つまり最後から2番目のレイヤー)。パラメータ3は0より大きいため、実行を継続し、「Push stack: 3」を出力します。

③プログラムは実行を継続し、関数catを呼び出し、再び新しい関数実行コンテキストに入り、パラメータa-1を使用してスタック(3番目のエントリ、最後から3番目の層)にプッシュし続け、ステップ②をループします。ここで、関数cat(a-1)が呼び出されるため、次のコード行「Pop: a」(この時点でaはまだ3です)、つまり「Pop: 3」が一時的に取り残され、スタックの最後から2番目の層に存在することに注意してください。

④ ②③を繰り返して、「Push: 2」、「Push: 1」、「Push: 0」を順に出力します。同時に、取り残される出力は、「Pop: 2(スタックの下から3番目の層)」、「Pop: 1(スタックの下から4番目の層)」、「Pop: 0(スタックの下から5番目の層)」です。

⑤ スタックの特性に応じて、残っている4つの出力項目が「スタックにプッシュ:3」、「スタックにプッシュ:2」、「スタックにプッシュ:1」、「スタックにプッシュ:0」の順に出力されます。
上記は実行コンテキストスタックの具体的な状況です。実際にコードを実際に実行していただければ、十分に理解できると思います。

3. 実行コンテキストスタック処理の詳細

関数が呼び出されるたびに、新しいコンテキストが実行されることは既に知られています。各実行コンテキストは、作成フェーズと実行フェーズの 2 つのフェーズに分かれています。作成フェーズ: プログラムが関数を呼び出すが、コードが実行されないフェーズを指します。
実行フェーズ: 変数の割り当てや関数の実行などのコード実行フェーズを指します。

1. 作成フェーズ

この段階で関数が呼び出されると、実行コンテキスト オブジェクト (executionContextObj) が作成されます。このオブジェクトには、スコープ チェーン オブジェクト (scopeChain)、変数オブジェクト (variableObject、VO と呼ばれます)、およびこのオブジェクトの 3 つのオブジェクトが含まれます。VO には、変数宣言 (variable)、関数宣言 (function)、パラメーター (arguments) などが含まれます。
これら 3 つのオブジェクトは、次の 3 つの手順で作成されます。
ステップ1: スコープチェーン(scopeChain)を初期化し、スタックメモリを割り当てる

ステップ2: パラメータ、関数、変数を作成する

ステップ3: コンテキストの「this」の値を決定する

次のコードを使用して上記の手順をさらに分析してみましょう。

関数cat(名前) {
    var a = '年々';
    var b = 関数 () {};
    this.name = 名前;
    関数c() {
        コンソールにログ出力します。
    }
    c();
}
cat('魚がいる');

このコードが関数 cat('有鱼') を呼び出すと、実行コンテキストは作成フェーズになり、コードは次のように解析されます。

cat実行コンテキストオブジェクト = {
    scopeChain: { ... }, // 1. スコープチェーンを作成し、スタックメモリを割り当てます。variableObject: { 2. 変数オブジェクトを作成します。arguments: { // 2.1 パラメータ 0 を解析します: '魚がいます',
            長さ: 1
        },
        name: '有鱼', // 2.1 パラメータを解析し、パラメータ名を作成し、パラメータを割り当てます c: function c() // 2.2 関数宣言 c を見つけ、c を属性として使用し、関数 c を値として使用します a: undefined, // 2.3 変数宣言 a を見つけ、undefined に初期化します。この段階では宣言部分のみを見て、値を割り当てません b: undefined // 2.3 変数宣言 b を見つけ、undefined に初期化します。この段階では宣言部分のみを見て、値を割り当てません },
    this: { 3. このオブジェクトを作成する this:cat('有鱼') // 3.1 この呼び出しのオブジェクトを指す name:undefined // 3.2 オブジェクトのプロパティ name は undefined に初期化される
    };
    c() //関数 c の実行コンテキストに再度入ります。cat 関数と同じですが、まだ展開されていません。}

コード分​​析を通じて、次のような結論を導き出すことができます。

①3つのステップの順序は間違えてはいけない ②VOステップでは関数宣言を先に実行し、次に変数宣言を実行する ③この段階ではパラメータのみ割り当て可能で、変数と関数は宣言のみ可能

2. 実装

この段階では、js インタープリターはコンテキスト内の関数コードを実行し、js コードを 1 行ずつ実行し、変数に値を割り当てます。
または、コードと組み合わせて分析します。

cat実行コンテキストオブジェクト = {
    スコープチェーン: { ... },
    変数オブジェクト: { 
        引数: { 
            0: 「魚がいる」
            長さ: 1
        },
        名前: 「魚がいる」 
        c: 関数c()、
        a: '年年', // 変数 a に値が割り当てられます b: 関数 b // 変数 b に値が割り当てられます },
    this: { 3. このオブジェクトを作成します this:cat('There is fish') 
        name:'有鱼' // オブジェクト属性名に値を割り当てる}
}

以上がJavaScriptにおける実行コンテキストとコールスタックの詳細な説明です。JavaScriptにおける実行コンテキストとコールスタックの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • JavaScript実行メカニズムの詳細な説明
  • JavaScriptの実行メカニズムを徹底的に理解する
  • JS 非同期実行の原則とコールバックの詳細
  • JavaScript での実行コンテキストと実行スタックの例の説明
  • JavaScript実行モデルの詳細な説明
  • Javascript 実行コンテキスト順序の詳細な説明
  • JavaScript モジュール エグゼキュータを手動で実装する方法
  • Javascript 非同期プロセス制御シリアル実行の詳細な説明
  • いくつかの面接の質問を使ってJavaScriptの実行メカニズムを調べる

<<:  Docker Compose を使用して nginx のロード バランシングを実装する方法

>>:  今日、今週、今月、先月のMySQLクエリデータ

推薦する

ウェブサイトのビジュアルデザイン(画像とテキスト)における情報伝達の役割と方法

現代の Web ビジュアル デザインは、初期の情報の積み重ねから、その後のグラフィックスと抽象化、そ...

フィボナッチ数列のJavaScript出力を実装する方法

目次トピック分析する基本的な解決策基本的な再帰再帰最適化要約するトピック私たちが答えなければならない...

LinuxサーバにおけるNginxとApacheの共存の実装方法の分析

この記事では、Linux サーバー上で Nginx と Apache の共存を実装する方法について説...

デザイン協会: なぜ間違った場所を探したのですか?

数日前、バスで仕事に行きました。バスのカードリーダーの実際の使用シーンを実際に見て、カードリーダーの...

srcまたはcss背景画像のurl値はbase64でエンコードされたコードです

ウェブ上の一部の画像の src または CSS 背景画像 URL の後に、data:image/pn...

折りたたまれたテーブル行要素のバグ

例を見てみましょう。コードは次の通り非常にシンプルです。コードをコピーコードは次のとおりです。 &l...

Dockerコンテナとローカルマシン間でファイルを転送する方法

ホストとコンテナ間でファイルを転送するには、コンテナの完全な ID が必要です。取得方法は以下の通り...

MySQL5.7.17 winx64 インストール バージョン構成方法 Windows Server 2008 R2 でのグラフィック チュートリアル

参考までに、Winでmysql5.7をインストールします。具体的な内容は次のとおりです。 @Auth...

Ubuntu 16.4 で完全に分散された Hadoop 環境を構築するための実践的なチュートリアル

序文この記事は主にubantu 16.4 Hadoop完全分散構築に関する関連コンテンツを紹介し、皆...

Zabbix で監視項目と集約されたグラフを設定するためのサンプルコード

1. ローカルマシンを監視するためにZabbixエージェントをインストールするエージェントソフトウェ...

mysql 実行プラン ID が空である (UNION キーワード) の詳細な説明

導入作業プロセス中に、遅いクエリが調整されることがあります。 MySQL SQL ステートメントのチ...

MySQL データベースのデータ テーブルの最適化、外部キーの分析、3 つのパラダイムの使用

この記事では、例を使用して、MySQL データベースのデータ テーブルの最適化、外部キーの使用、およ...

MYSQLストアドプロシージャ、つまり一般的な論理知識のポイントの要約

MySQL ストアド プロシージャ1. ストアドプロシージャ構文(フォーマット)を作成する 区切り文...

JavaScript ドラッグタイム ドラッグケースの詳細な説明

目次DragEvent インターフェースデータ転送インターフェースの概要DataTransfer の...

Dockerコンテナのタイムゾーン調整操作

Docker コンテナのタイムゾーンがホストマシンと一致しているかどうかを確認するにはどうすればよい...