JavaScriptのイベントループとコールスタックの仕組み

先生

JavaScriptの非同期処理、もう迷わない!イベントループとコールスタックの仕組みを徹底解説!

JavaScriptのイベントループとは?

JavaScriptはシングルスレッドで動作しますが、非同期処理を実現するためにイベントループという仕組みを持っています。イベントループは、コールスタック、タスクキュー(またはメッセージキュー)、そしてWeb API(ブラウザ環境の場合)やNode.js API(Node.js環境の場合)といった要素で構成されています。

イベントループの役割は、コールスタックが空になるのを監視し、タスクキューに積まれたタスクを順番にコールスタックに移動させることです。これにより、JavaScriptは非同期処理を効率的に処理し、UIのフリーズを防ぐことができます。

イベントループを理解することで、JavaScriptの非同期処理の挙動を予測し、より効率的なコードを書くことができるようになります。

コールスタックの役割

コールスタックは、JavaScriptエンジンが実行中の関数を追跡するためのデータ構造です。関数が呼び出されると、その関数がコールスタックにプッシュされ、関数の実行が完了すると、コールスタックからポップされます。

コールスタックはLIFO(Last-In, First-Out:後入れ先出し)の原則に従います。つまり、最後にプッシュされた関数が最初にポップされます。


function firstFunction() {
  console.log('firstFunction start');
  secondFunction();
  console.log('firstFunction end');
}

function secondFunction() {
  console.log('secondFunction start');
  thirdFunction();
  console.log('secondFunction end');
}

function thirdFunction() {
  console.log('thirdFunction start');
  console.log('thirdFunction end');
}

firstFunction();

上記のコードを実行すると、コンソールには次のように出力されます。


firstFunction start
secondFunction start
thirdFunction start
thirdFunction end
secondFunction end
firstFunction end

これは、firstFunctionがコールスタックにプッシュされ、次にsecondFunction、そしてthirdFunctionがプッシュされるからです。thirdFunctionが完了すると、ポップされ、secondFunctionfirstFunctionの順にポップされます。

イベントループの動作

イベントループは、継続的にコールスタックとタスクキューを監視しています。コールスタックが空になると、イベントループはタスクキューからタスクを取り出し、コールスタックにプッシュします。これにより、非同期処理の結果(例えば、setTimeoutやXMLHttpRequestのコールバック関数)が実行されます。


console.log('start');

setTimeout(function() {
  console.log('setTimeout callback');
}, 0);

console.log('end');

上記のコードを実行すると、コンソールには次のように出力されます。


start
end
setTimeout callback

これは、setTimeoutのコールバック関数がタスクキューに追加され、コールスタックが空になった後で実行されるからです。setTimeoutの遅延時間が0であっても、コールバック関数はタスクキューを経由して実行されるため、console.log('end')の後に実行されます。

この挙動を理解することは、JavaScriptで非同期処理を扱う上で非常に重要です。

タスクキュー(メッセージキュー)

タスクキューは、非同期処理の結果として実行されるコールバック関数が格納される場所です。setTimeout、setInterval、addEventListenerなどの非同期処理によって生成されたタスクは、このキューに追加されます。

イベントループは、コールスタックが空になったときに、このタスクキューからタスクを取り出して実行します。タスクキューはFIFO(First-In, First-Out:先入れ先出し)の原則に従います。

参考リンク

まとめ

JavaScriptのイベントループ、コールスタック、タスクキューの仕組みを理解することで、非同期処理の挙動を正確に把握し、より効率的で信頼性の高いコードを書くことができます。これらの概念は、JavaScriptを深く理解するために不可欠です。