JavaScript アンダー ザ フード: イベント ループ
ゼロから機能を調べてJavaScriptをマスターしよう
未定義のエラーに直面したり、変数のスコープを特定するのに苦労したことはありませんか?
コードがどのように動作するかを知らずにエラーをデバッグするのは、本当に時間がかかります。
このブログでは、 、、 などの高度な概念が実際にどのようevent loopに機能するかを説明します。execution contextcall stackcallback queue
免責事項 — 概念は信じられないほど知識集約的で相互に関連しているため、まばたきさえしないでください。
JavaScript エンジン
Google の V8 エンジンは、JavaScript エンジンのよく知られた例です。たとえば、Chrome と Node.js はどちらも V8 エンジンを採用しています。基本的に、V8 エンジンは 2 つの部分で構成されています —
- Call Stack :すべてのコードはその中で実行されます。スタック データ構造のように機能します。つまり、LIFO (後入れ先出し) の概念に従います。
- メモリ ヒープ:メモリ割り当てが発生する場所。ヒープ データ構造とは異なり、これは単なるメモリです。
グローバル実行コンテキスト (GEC) は、スクリプト ファイルを受信するたびに JavaScript エンジンによって作成されるデフォルトの実行コンテキストです。
関数内にないすべての JavaScript コードは で実行されGECます。次の手順は、次の場所で実行されますGEC—
- グローバル スケールですべての変数と関数を格納するためのメモリ空間を構築する
- グローバル オブジェクトを生成します。
- キーワードを生成する
this
コードが実行される場所に応じて、 の場所が決まりthisます。たとえば、Node.js では個別のグローバル オブジェクトを指しますが、ブラウザーではwindowオブジェクトを指します。
呼び出しスタック (または関数実行スタック)
single-threadedすでに聞いたとおり、JavaScript はです。しかし、それは実際にはどういう意味ですか?
これは、JavaScript エンジンにcall stackまたはが 1 つだけ含まれていることを意味しますfunction execution stack。
- 私たちが知っているように、コンパイラが最初にコードを調査するときはいつでも、JS エンジンはコンパイラによって
Global Execution Contextまたはを作成するように求められ、 .GECCall Stack - コード全体が で 1 つずつ実行され
Global Execution Context、関数定義または変数宣言用にメモリが割り当てられ、そこに格納されます。 - ただし、関数呼び出しが見つかると、関数のコードを実行するために
Functional Execution ContextorFECが作成され、call stack. - インタープリターは、関数が
call stack終了するたびに から関数を削除します。関数は、そのスコープまたは return ステートメントの終わりに達したときに終了します。 - 最後に、コード全体を実行すると
GEC、Call Stack.
心配しないで、例を挙げて説明しましょう。
function f1{
console.log('f1');
}
f1();
console.log('end');
ステップ 2: —この例では、最初の行が実行されますf1。メモリが割り当てられ、f1その定義が保存されます。
ステップ 3: — 2 行目で、関数が呼び出されます。この関数呼び出しでは、Function Execution Context orFECが作成され、 の上に格納されCall Stackます。
ステップ 4: —これで、全体f1()が 1 行ずつ実行され、実行が終了すると から削除されますCall Stack。
ステップ 5: —次に、最後の行console.log('end')が実行され、コンソールに「end」が出力されます。最後に、コード全体を実行するGlobal Execution Contextと、Call Stack.
JS は非同期タスクをどのように管理しますか?
JavaScript は、よく知られているように、同期型のシングル スレッド言語 (一度に 1 つのタスク) であり、call stack内部にあるものは何でもすぐに実行されるシングル スレッドです。
しかし、5 秒後に何かを実行する必要がある場合はどうなるでしょうか。の中でそれを行うことはできますcall stackか?
いいえ、できません。call stackタイマーがないからです。しかし、どうすればそれができるのでしょうか?
ここで、JavaScript ランタイムの出番です。
私が今あなたに言うと、悲嘆に暮れる可能性があります.JavaScriptsetTimeout()の一部ではありませんが、console.log()DOMイベントはすべて、 JavaScriptエンジンにアクセスしてGlobal Execution Context(GEC)ですべてのプロパティを使用できるWeb APIの一部です。グローバル オブジェクト。これらのWeb APIは非同期と呼ばれます。window
コールバック キューとは
「コールバック キュー」または「タスク キュー」と呼ばれるタスクのキューは、コール スタックの現在の役割が完了した後に実行されるものです。Web API に登録されているタスクは、Web API からコールバック キューに移動します。
コール スタックは、タスクがキューに追加された順序で処理されることを意味するコール スタックとは対照的に、タスクが FIFO 順 (先入れ先出し) で処理されることを意味するキュー データ構造のように機能します。
イベントループとは?
JavaScript イベント ループは、コール スタックが空になるとすぐに、タスクをコールバック キューからコール スタックに FIFO 順で追加します。
コール スタックが現在何らかのコードを実行している場合、イベント ループはブロックされ、スタックが再び空になるまでキューから追加の呼び出しを追加しません。これは、JavaScript コードが run-to-completion 方式で実行されるためです。
上記の概念を例で理解しましょう。
- 最初に、
Global Execution Context内部でコード用に作成され、コードをcall stack1GEC行ずつ実行します。 GEC最初の行を実行し、コンソールに「開始」を出力します。- 2 行目を実行すると、
setTimeout()Web API が呼び出され、setTimeout()タイマー機能にアクセスできるようになります。5000msその後、遅延時間として設定できるようになります。 callBack()を介して関数を渡す場合setTimeout()、 はcallBack()Web Web API 経由のコール バックとして登録されます。- 次に、
GEC最初の行を実行し、コンソールに「End」を出力します。 - すべてのコードが実行される
GECと、call stack. - その後
5000 millisecond、 にcallBack()登録されている関数をweb API内に移動しcall Back Queueます。 Event loopcallBack()関数を に入れcall Stackたら、すべての作業が完了します。最後に、callBack()関数が実行され、「Call Back」がコンソールに出力されます。
function f1() {
console.log('f1');
}
function f2() {
console.log('f2');
}
function main() {
console.log('main');
setTimeout(f1, 0);
f2();
}
main();
「f1」が「f2」の前に印刷されると考えている場合は、間違っています。そうなる -
main
f2
f1
説明した JavaScript のメカニズムは、あらゆるコールバック関数または API リクエストに適しています。
ランタイム環境内で 2 番目の例がどのように機能するかを段階的に観察しましょう。
- 最初
GECは 内に作成され、call stackコードは 内で 1 行ずつ実行されGECます。すべての関数定義をMemory Heapに格納します。 - が
main()呼び出されると、 aFunction Execution Context (FEC)が作成され、コール スタック内に入ります。その後、main()関数のすべてのコードが行ごとに実行されます。 - メインという単語を出力するコンソールログがあります。したがって、
console.log('main')実行されてスタックから出ます。 setTimeout()ブラウザ API が実行されます。コールバック関数はそれをコールバック キューに入れます。しかし、スタックでは、通常どおり実行が行われるためf2()、スタックに入ります。実行のコンソール ログf2()。どちらもスタックから出ます。- そして、これ
main()もスタックから飛び出します。 - イベント ループは、コール スタックが空であることを認識し、キューにコールバック関数があります。したがって、コールバック関数
f1()は によってスタックに入れられますevent loop。実行が開始されます。コンソール ログが実行f1()され、スタックからポップアウトされます。最後に、スタックとキューには、さらに実行するものは何もありません。
それは私の練習とメモです。役に立った場合は、下の拍手アイコンをクリックしてサポートを示してください。mediumでフォローできます。

![とにかく、リンクリストとは何ですか?[パート1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































