どうやってJavaScriptは実行されているのか

2021年1月15日JavaScript

JavaScriptはどうやって実行されているのでしょうか?
JavaScriptの裏側で動いているコンパイルされてから実行するまでの詳しい部分をまとめました。

どうやってJavaScriptは実行されているのか

JavaScriptのコードがコンパイルされた後、実行されると前回の記事でまとめました。


グローバル実行コンテキスト(Global Execution Context)がトップレベルコードのために作られます。
そしてグローバル実行コンテキスト内でトップレベルコードが実行されます。
そしてコールバックをもって関数が実行されます。

トップレベルコードというのは、関数の中にはありません。関数外にあるコードのみが実行されます。
関数は呼ばれたときに実行されるためです。

実行コンテキストについて

コンテキスト(Context)とは、文脈のことです。プログラムの世界でいう実行コンテキストとは、コードを実行する際の文脈、つまり状況・環境のことです。

たとえばコンビニでお弁当を購入するとします。
お弁当の具材というのが中身でいわばJavaScriptのコードのことだとすれば、
そのお弁当を購入するためにはレシートやお箸が必要だったり、それらをまとめていれる容器が必要になります。
その容器が実行コンテキストということになります。

実行コンテキストには、2種類あります。

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

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

グローバル実行コンテキストはたった一つだけの実行コンテキストです。トップレベルコードが実行されます。
実行というのはコンピュータがCPUで機械語を実行することです。

グローバル実行コンテキストで扱えるものは、

  • 実行中のコンテキスト内の変数・関数
  • グローバルオブジェクト
  • thisキーワード

が使用可能です。

関数の実行コンテキスト

関数の実行コンテキストは、関数ごとに存在します。オブジェクトに付随しているメソッドもまた同じです。
クリックイベントなどのコールバックがあれば、実行されます。
関数実行コンテキストで扱えるものは、

  • 実行中のコンテキスト内の変数・関数
  • arguments
  • super(特殊な環境でのみ使用可能)
  • thisキーワード
  • 外部変数

外部変数とは関数実行コンテキストの外で宣言されている変数のことです。

たとえば

//ここがグローバルコンテキスト
let number = 12;
function hello() {
  //ここが関数コンテキスト
  console.log(this, arguments, number)
}
hello();

それぞれの関数が自身の実行コンテキストをもっています。そのため、関数の中で宣言された変数はその変数環境でのみ実行されます。
しかし変数は関数の外にもアクセスすることができます。それがスコープチェーンというものです。
スコープチェーンとは、基本的には関数内の変数がその関数の外側にアクセスすることです。
詳しくは次の記事を参照してみてください。

コールスタックって何?

コールスタックとは、JSエンジンの中にある実行中のコードがたどってきたコンテキストの積み重ねです。
その積み上げているトップにある実行コンテキストが、常に現在実行中のコンテキストとなります。
実行が終わるとその山から取り除かれます。
そしてその次の実行コンテキストを実行します。
このようなスタックの仕組みを後入れ先出しという意味のLIFO(Last In, First Out)といいます。
具体例をみてみましょう。

実行コンテキストとコールスタックの具体例

たとえば次のようなコードがあります。


  const name = 'Sasa';

  const first = () => {
    let a = 1;
    const b = second(2,4);
    a = a + b;
    return a;
  }

  function second(x, y) {
    var c = 2;
    return c;
  }

  const x = first();

上のコードでは、まず最初にコールスタックにはグローバル実行コンテキストが積み上げられます。
そして、最後のコードをみると、first();とあるので、次にfirstの関数の実行コンテキストがコールスタックに積み上げられます。
first()の中にはsecond()が存在します。そのため、そこでfirst()の処理はとまり、secondをコールスタックに積み上げます。
そして、secondが実行されるまでは他の実行コンテキストは実行されません。
それは、JavaScriptがシングルスレッドのためです。

secondが実行される、つまり最後のreturnを返すとコールスタックから取り除かれます。
そしてトップにきたfirstが実行されます。
そして、それはconst b = second(2, 4);のところに戻ることを意味します。
そしてfirst()が実行されると、const x = first()というグローバル実行コンテキストが実行されます。

ブラウザの開発ツールのsourcesのタブの中のCall Stackで確認することができます。