1.2 JS Engine and Runtime
What is a JavaScript Engine?β
A JavaScript engine is a program that reads, analyzes, and executes JavaScript code. Each browser has its own built-in JavaScript engine.
| Engine | Browser/Environment | Developer |
|---|---|---|
| V8 | Chrome, Edge, Node.js, Deno | |
| SpiderMonkey | Firefox | Mozilla |
| JavaScriptCore (Nitro) | Safari, WebKit | Apple |
| Hermes | React Native | Meta |
How JS Engines Workβ
Let's look at the process of executing JavaScript code step by step.
Step 1: Parsing Source Codeβ
The engine reads text JavaScript code and splits it into tokens.
// This code
const x = 10 + 20;
// Is split into these tokens
// [const] [x] [=] [10] [+] [20] [;]
Step 2: Building the ASTβ
Tokens are transformed into a tree structure called an AST (Abstract Syntax Tree).
// AST for const x = 10 + 20; (simplified)
{
type: "VariableDeclaration",
kind: "const",
declarations: [{
type: "VariableDeclarator",
id: { type: "Identifier", name: "x" },
init: {
type: "BinaryExpression",
operator: "+",
left: { type: "Literal", value: 10 },
right: { type: "Literal", value: 20 }
}
}]
}
Step 3: Bytecode Generation (Interpreter)β
The AST is converted into bytecode. Bytecode is higher-level than machine code but executes faster than source code.
In the V8 engine, the Ignition interpreter handles this step.
Step 4: JIT Compilationβ
When frequently executed code (Hot Code) is detected, the JIT (Just-In-Time) compiler compiles it to machine code to improve performance.
In V8, the TurboFan optimizing compiler handles this.
Source Code
β Parsing
AST
β Compilation
Bytecode ββ Executed by Ignition interpreter
β Hot Code detected
Optimized Machine Code β JIT compiled by TurboFan
V8 Engine Deep Diveβ
V8 is Google's high-performance JavaScript engine, used in Chrome and Node.js.
V8 Memory Structureβ
βββββββββββββββββββββββββββββββββββ
β V8 Heap Memory β
βββββββββββββββββββββββββββββββββββ€
β New Space (Young Generation) β β Newly created objects
β (1~8MB) β
βββββββββββββββββββββββββββββββββββ€
β Old Space (Old Generation) β β Long-lived objects
β (default max ~1.5GB) β
βββββββββββββββββββββββββββββββββββ€
β Code Space β β Compiled code
βββββββββββββββββββββββββββββββββββ€
β Large Object Space β β Large objects (>512KB)
βββββββββββββββββββββββββββββββββββ
Garbage Collectionβ
V8 uses the Mark-and-Sweep algorithm to automatically free memory for objects that are no longer referenced.
function createData() {
// After function runs, these objects have no references β GC targets
const bigArray = new Array(1000000).fill(0);
const obj = { data: bigArray };
return obj.data[0]; // Only returns the number 0
} // bigArray, obj freed by GC
let result = createData(); // 0
// result = 0, and bigArray/obj already freed
Browser Runtimeβ
The JavaScript engine alone cannot manipulate the DOM or make HTTP requests. It works together with Web APIs provided by the browser.
Browser Runtime Componentsβ
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Browser β
β βββββββββββββββββββ ββββββββββββββββββββββββββ β
β β JavaScript β β Web APIs β β
β β Engine β β - DOM β β
β β (V8/Spider β β - Fetch API β β
β β Monkey etc) β β - setTimeout β β
β β β β - Canvas API β β
β β βββββββββββββ β β - Web Storage β β
β β β Call Stackβ β β - WebSocket β β
β β βββββββββββββ β ββββββββββββββββββββββββββ β
β βββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββββββββββββ β
β β Event Loop + Callback Queue β β
β βββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
Browser-Only Global Objectsβ
// window object (global object in browsers)
console.log(window.innerWidth); // Browser window width
console.log(window.location.href); // Current URL
// document object (DOM access)
const btn = document.querySelector('#myBtn');
btn.addEventListener('click', () => alert('Clicked!'));
// navigator object (browser/device info)
console.log(navigator.userAgent);
console.log(navigator.language); // 'en-US'
// history object (browser history)
history.back();
history.pushState({}, '', '/new-url');
Event Loop (Brief Introduction)β
JavaScript is single-threaded but can handle asynchronous processing. The event loop manages the Call Stack and Callback Queue.
console.log('1. Start');
setTimeout(() => {
console.log('3. setTimeout callback (after 1 second)');
}, 1000);
console.log('2. End');
// Output order:
// 1. Start
// 2. End
// 3. setTimeout callback (after 1 second)
Event loop details are covered in depth in Ch6.
Node.js Runtimeβ
Node.js is a runtime environment that allows JavaScript to run outside of browsers. Ryan Dahl built it on top of the V8 engine in 2009.
Node.js Componentsβ
βββββββββββββββββββββββββββββββββββββββββββ
β Node.js β
β βββββββββββββββββ βββββββββββββββββββ β
β β V8 Engine β β Node.js APIs β β
β β β β - fs (files) β β
β β JavaScript β β - http β β
β β Execution β β - path β β
β βββββββββββββββββ β - os β β
β β - crypto β β
β βββββββββββββββββ βββββββββββββββββββ β
β β libuv β β
β β (Event Loop β β
β β + I/O) β β
β βββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββ
Node.js-Only Featuresβ
// File system access (not available in browsers)
import { readFileSync, writeFileSync } from 'fs';
const content = readFileSync('./data.txt', 'utf-8');
console.log(content);
writeFileSync('./output.txt', 'Hello Node.js!');
// HTTP server (not available in browsers)
import { createServer } from 'http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World!');
});
server.listen(3000, () => console.log('Server running: http://localhost:3000'));
// process object (Node.js global)
console.log(process.version); // Node.js version
console.log(process.platform); // 'win32', 'linux', 'darwin'
console.log(process.env.PATH); // Environment variables
Browser vs Node.js Comparisonβ
| Item | Browser | Node.js |
|---|---|---|
| Global Object | window | global, globalThis |
| Module System | ESM (import/export) | ESM + CJS (require) |
| DOM | Yes | No |
| File System | No | Yes |
| HTTP Server | No | Yes |
| Native Modules | Web APIs | Node.js APIs |
| Sandbox | Yes (security restricted) | No (unrestricted) |
Environment Detection with globalThisβ
// Works in both browser and Node.js
if (typeof window !== 'undefined') {
console.log('Browser environment');
console.log(window.location.href);
} else {
console.log('Node.js environment');
console.log(process.version);
}
// Better approach: use globalThis
console.log(globalThis); // Browser: window, Node.js: global
Pro Tipsβ
Coding Patterns for V8 Optimizationβ
V8 uses Hidden Classes and Inline Cache techniques to optimize object access:
// Good: always initialize properties in the same order
class Point {
constructor(x, y) {
this.x = x; // always x first
this.y = y; // always y second
}
}
// Bad: dynamically adding properties (changes Hidden Class)
const p1 = {};
p1.x = 1;
p1.y = 2; // Hidden Class change β de-optimization
// Maintain numeric types (V8 uses internal representations: Smi, Double, Object)
const arr = [1, 2, 3]; // Smi array (fast)
arr.push('text'); // Changes to Object array (slower)
arr.push(1.5); // Changes to Double array