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クエリデータ

推薦する

フォーム要素の垂直方向の中央揃えに最適なソリューション

コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC "...

HTMLタグIDは変数にできる

<table id=" <%=var1%>">、var1...

JavaScript ECharts の使用方法の説明

以前、プロジェクトを行う際に ECharts を使用しました。今日はそれをメモとして整理し、より多く...

VMware 15.5 バージョンのインストール Windows_Server_2008_R2 システム チュートリアル図

1. VMware 15.5から新しい仮想マシンを作成する1. VMware を開き、ホームページで...

CentOS 7のインストールと設定方法のグラフィックチュートリアル

この記事は、CentOS 7の詳細なインストールチュートリアルを参考のために記録します。具体的な内容...

Vue の computed と watch の違いを理解する方法

目次概要計算された監視プロパティを監視する要約する概要Vue プロジェクトでは、computed と...

MySql でデータの重複挿入を回避する 3 つの方法

序文MySql で主キーの競合または一意キーの競合が発生した場合、挿入方法に応じてエラーを回避するた...

vue data が関数である理由をご存知ですか?

公式サイトの説明: コンポーネントを定義する場合、コンポーネントは複数のインスタンスを作成するために...

フレックスレイアウトの改行スペースでの align-content の使用

1. この記事で実装した効果図は以下のとおりです。レイアウトの右側に Flex レイアウトを使用し、...

Linux に起動方法を追加する (サービス/スクリプト)

システムの起動時に読み込む必要がある設定ファイル/etc/profile、/root/.bash_p...

HTML テーブルタグチュートリアル (3): 幅と高さの属性 WIDTH、HEIGHT

デフォルトでは、テーブルの幅と高さはコンテンツに応じて自動的に調整されます。テーブルの幅と高さを手動...

JavaScript配列の一般的なメソッドの詳細な説明

目次一般的な配列メソッドポップ()シフト解除()シフト()スライス()スプライス()配列から重複した...

あなたを救うために、私のテーブルは何を使えばいいでしょうか (Haiyu Blog)

テーブルはかつて、Web ページの開発、つまりレイアウトにおいて非常に重要な役割を果たしていました。...

Dockerカスタムネットワークコンテナ相互接続

目次序文-リンクカスタムネットワーク質問する序文前回は、 -Linkパラメータを使用してコンテナ間の...

MySQL 8.0.23のルートパスワードをリセットするための最適なソリューション

この方法は2021年2月7日に編集されました。私が使用しているバージョンは8.0.23です。事件の原...