JavaScriptコールスタック

概要:このチュートリアルでは、関数呼び出しを追跡するメカニズムであるJavaScriptコールスタックについて学習します。

JavaScriptコールスタック入門

コールスタックは、JavaScriptエンジンが複数の関数を呼び出すコード内の場所を追跡する方法です。現在実行されている関数と、その関数内から呼び出された関数の情報が保持されます…。

また、JavaScriptエンジンは、実行コンテキストを管理するためにコールスタックを使用します。

  • グローバル実行コンテキスト
  • 関数実行コンテキスト

コールスタックは、後入れ先出し(LIFO)の原則に基づいて動作します。

スクリプトを実行すると、JavaScriptエンジンはグローバル実行コンテキストを作成し、コールスタックの一番上にプッシュします。

関数が呼び出されるたびに、JavaScriptエンジンはその関数の関数実行コンテキストを作成し、コールスタックの一番上にプッシュして、関数の実行を開始します。

関数が別の関数を呼び出す場合、JavaScriptエンジンは呼び出される関数の新しい関数実行コンテキストを作成し、コールスタックの一番上にプッシュします。

現在の関数が完了すると、JavaScriptエンジンはそれをコールスタックからポップし、中断したところから実行を再開します。

コールスタックが空になると、スクリプトは停止します。

JavaScriptコールスタックの例

次の例から始めましょう。

function add(a, b) {
    return a + b;
}

function average(a, b) {
    return add(a, b) / 2;
}

let x = average(10, 20);
Code language: JavaScript (javascript)

JavaScriptエンジンがこのスクリプトを実行すると、グローバル実行コンテキスト(main()またはglobal()関数で表されます)をコールスタックに配置します。

JavaScript Call Stack - main

グローバル実行コンテキストは作成フェーズに入り、実行フェーズに移行します。

JavaScriptエンジンはaverage(10, 20)関数の呼び出しを実行し、average()関数の関数実行コンテキストを作成して、コールスタックの一番上にプッシュします。

JavaScript Call Stack - step 2

average()関数がコールスタックの一番上にあるため、JavaScriptエンジンはaverage()の実行を開始します。

average()関数はadd()関数を呼び出します。この時点で、JavaScriptエンジンはadd()関数の別の関数実行コンテキストを作成し、コールスタックの一番上に配置します。

JavaScript Call Stack - step 3

JavaScriptエンジンはadd()関数を実行し、コールスタックからポップします。

JavaScript Call Stack - step 4

この時点で、average()関数はコールスタックの一番上にあり、JavaScriptエンジンはそれを実行し、コールスタックからポップします。

JavaScript Call Stack - step 5

これでコールスタックが空になったため、スクリプトの実行が停止します。

JavaScript Call Stack - empty stack

次の図は、すべての手順におけるコールスタックの全体的な状態を示しています。

JavaScript Call Stack

スタックオーバーフロー

コールスタックには、ホスト環境(WebブラウザまたはNode.js)の実装に応じて、固定サイズがあります。

実行コンテキストの数がスタックのサイズを超えると、スタックオーバーフローエラーが発生します。

たとえば、終了条件のない再帰関数を実行すると、JavaScriptエンジンはスタックオーバーフローエラーを発行します。

function fn() {
    fn();
}

fn(); // stack overflowCode language: JavaScript (javascript)

非同期JavaScript

JavaScriptはシングルスレッドのプログラミング言語です。これは、JavaScriptエンジンにコールスタックが1つしかないことを意味します。したがって、一度に1つのことしかできません。

スクリプトを実行する場合、JavaScriptエンジンはコードを上から下へ、1行ずつ実行します。言い換えれば、同期です。

非同期とは、JavaScriptエンジンが別のタスクの完了を待機している間に他のタスクを実行できることを意味します。たとえば、JavaScriptエンジンは次のことができます。

  • リモートサーバーからのデータのリクエスト。
  • スピナーを表示する
  • データが利用可能になったら、Webページに表示します。

これを行うために、JavaScriptエンジンはイベントループを使用します。これは、次のチュートリアルで説明します。

まとめ

  • JavaScriptエンジンは、実行コンテキストを管理するためにコールスタックを使用します。
  • コールスタックは、LIFO(後入れ先出し)の原則に基づいて動作するスタックデータ構造を使用します。
このチュートリアルは役に立ちましたか?