JS Engine:
- Program that executes JS code. Ex. Google's V8.
- V8 powers Chrome, Node.js
- Other browsers have their own JS Engine.
JS Engine has 2 parts:
- Call Stack: Where our code is executed using execution context.
- Heap: Unstructured memory pool, used for storing objects.
Every c/r program needs to be converted to machine code. Done via two processes:
1. Compilation: Entire code is converted into machine code at once, written to a binary file that can be execued by a computer.
Source Code -(compiled)-> Binary Code[Portable File] -(executed)-> Pgm Run
Execution can happen way after compilation.
2. Interpretation: Interpreter runs through the source code, executes it line by line.
Source code -(execution line by line)-> Pgm Run
- Here code still needs to be converted to machine code.
- They are much slower as compared to compiled l/gs.
3. JIT i.e Just in Time Compilation:
- Modern JS Engine is a mix of compilation & interpretation to make it fast.
- Entire code is converted into machine code at once, then executed immediately. Source Code -(compiled)-> Machine code -(executed)-> Pgm Run
- There is no intermediate portable file to execute.
- Execution happens immediately after compilation.
- Hence, JS now is much faster than interpreted l/gs due to this technique.
Compilation Process in JS:
Step 1. Parsing:
- Our code is Parsed i.e read by JS engine into AST or Abstract Syntax Tree.
- Works by splitting code into a tree based on keywords like const, let, function etc which are meaningful to the l/g.
- Then saves the code into a tree in a structured way.
- Also check for any syntax errors.
- AST has nothing to do with the DOM tree. AST is just representation of our code inside the JS Engine.
Step 2, 3[combined]: Compilation + Execution
- AST is compiled and immediately executed after it, using JIT.
- Execution happens in Call stack.
- Modern JS has clever optimisation strategies, i.e they quickly create an unoptimized version of machine code in begining so as to start execution asap.
- In the background, this code is again recompiled during an already running pgm execution.
- Done in mutiple iterations, and after each optimisation the unoptimized code is swapped with newly optimized code without ever stopping the code execution. This makes V8 so fast.
- All this parsing, compilation, execution happens in some special thread inside JS Engine which we can't access using our code completely separate from the main thread which is running our code using call stack.
- JS is no more just interpreted l/g. It has JIT compilation which makes it way faster than interpreted l/gs.
JS Runtime = JS Engine + Web APIs + C/B Queue
- JS Runtime: Container including all the things that we need to use JS.
- Heart of any JS runtime is JS Engine.
- Without JS Engine, there is no runtime hence no JS at all.
- JS Engine alone is not enough, we need access to Web APIs like DOM, Fetch, Timers etc.
- Web APIs: Functionality provided to engine by runtime, but not part of JS engine. Ex. window object in browser, global object in node.
- Callback Queue is a data structure containing all the functions ready to be executed. Ex. click, timer, data etc
- DOM Event handler fns are also called as callback fns.
- When Call stack is empty, callback fn is shifted from C/B queue to Call stack for execution.
- The continuous checking & shifting is performed by Event Loop.
- Event loop is something which enables JS to have a non-blocking concurrency model.
- For node, we don't have Web APIs provided by browser. We have something called as C++ bindings & thread pool.
How JS Code executes on the Call Stack
- JS has single thread of execution, hence can do only thing at a time. Hence, no multiasking in JS.
- APIs are provided by environment, but not the part of language. Ex. Web APIs like Timers, Fetch, DOM, Geolocation etc.
- Callback Queue: Ready to be executed callback fns that are attached to some event which has occurred.
- Whenever call stack is empty, event loop transfers callback from calback to queue to call stack for execution.
- Event loop is hence an essential piece which makes Async behavior in JS possible.
- Concurrency Model: How a l/g handles multiple things happening at the same time.
- Essential parts of JS Runtime:
- Call Stack
- Web APIs
- Callback Queue
- Event loop
- Everything related to DOM is part of Web APIs, not JS.
- Image loading happens in async way, had it been in sync way then it would have been blocking i.e not on main thread rather Web APIs environment.
- All the event listeners, .then() etc work happens in WEb APIs environment and not on call stack.
- Callback fns are placed in callback queue waiting for them to be executed onn call stack.
- Callback queue is like a todo list which a call-stack has to complete.
- Duration mentioned is the minimum delay before for execution, and not the time for execution.
- Callback queue also contains callbacks coming from DOM events, clicks, keypress etc. DOM events are not async behavior, but they use callback queue for their execution.
- イベント ループは、コールバック キューが空になるまでチェックし続けます。コール スタックに配置された各コールバックは、イベント ループ ティックとして呼び出されます。
- イベント ループは JS ランタイム全体を調整します。
- 非同期コードはエンジン内で実行されないため、JS 自体には時間の感覚がありません。非同期動作を管理するランタイムと、実行するコールバックを決定するイベント ループです。
- エンジンまたは呼び出しスタックは、単に与えられたコードを実行します。
- 画像がロードされるとき、イベント リスナーはロード イベントが発生するまで Web API 環境で待機し続けます。起動されると、それのみがコールバック fn としてコールバック キューに送られ、コール スタック上でその順番が実行されるのを待ちます。
マイクロタスクキュー:
- Promise からのコールバックはコールバック キューに送られず、マイクロタスク キューに送られます。
- このキューはコールバック キューよりも高い優先度を持ちます。
- イベント ループは最初にこのキューをチェックし、最初にそのタスクをすべて実行してから、実行のためにコールバック キューに移動します。
- Promise のコールバックはマイクロタスクと呼ばれ、そのためマイクロタスク キューと呼ばれます。他にもマイクロタスクがありますが、現時点ではここでは関係ありません。 イベント ループは、各コールバックがいつ実行されるかを決定します。コールバックキューと比較してマイクロタスクに高い優先度を与えます
- マイクロタスクは、他のすべての通常のコールバック キューの前にインラインでカットできます。
- Promise.resolve() : すぐに解決される Promise を作成し、その成功値が引数として内部に渡されます。 then() コールバックは、解決された値を引数として呼び出します。
リーリー
- マイクロタスク キューに多数のマイクロタスクがある場合、または時間のかかるマイクロタスクがある場合、マイクロタスク キューがコールバック キューを枯渇させる可能性もあります。
リーリー
The above is the detailed content of JavaScript Engine. For more information, please follow other related articles on the PHP Chinese website!