JavaScript Execution in Browser
1. Loading Phase
HTML Parsing
// Regular script loading - blocks parsing
<script src="app.js"></script>
// Async loading - doesn't block parsing
<script async src="app.js"></script>
// Defer loading - executes after HTML parsing
<script defer src="app.js"></script>
Loading Sequence
- Browser receives HTML
- HTML parser starts parsing HTML document
- Creates DOM (Document Object Model)
- Encounters
<script>
tag- Without async/defer: Stops parsing, downloads, executes
- With async: Downloads in parallel, executes when ready
- With defer: Downloads in parallel, executes after parsing
2. Compilation Phase
Just-In-Time (JIT) Compilation
// V8 Engine Phases:
// 1. Source Code
function add(a, b) {
return a + b;
}
// 2. Abstract Syntax Tree (AST)
{
"type": "FunctionDeclaration",
"id": { "type": "Identifier", "name": "add" },
"params": [
{ "type": "Identifier", "name": "a" },
{ "type": "Identifier", "name": "b" }
],
// ... more AST nodes
}
// 3. Bytecode
// 4. Machine Code (for hot functions)
3. Creation Phase (Memory Allocation)
Global Execution Context Creation
// 1. Global Object Creation
window; // or global in Node.js
// 2. this Binding
this === window; // true in browser's global scope
// 3. Variable Hoisting
console.log(name); // undefined
var name = "John";
// 4. Function Hoisting
sayHello(); // "Hello"
function sayHello() {
console.log("Hello");
}
Scope Chain Creation
// Lexical Scope Example
const global = "I'm global";
function outer() {
const outer = "I'm outer";
function inner() {
const inner = "I'm inner";
console.log(global, outer, inner);
}
inner();
}
// Scope Chain: inner -> outer -> global
4. Execution Phase
Call Stack Operations
function first() {
console.log('First');
second();
}
function second() {
console.log('Second');
third();
}
function third() {
console.log('Third');
}
first();
// Call Stack Sequence:
// 1. main()
// 2. first()
// 3. second()
// 4. third()
// Then unwinding...
Event Loop and Task Queues
// 1. Synchronous Code
console.log('Start');
// 2. Macrotask (setTimeout)
setTimeout(() => {
console.log('Timeout');
}, 0);
// 3. Microtask (Promise)
Promise.resolve()
.then(() => console.log('Promise'));
console.log('End');
// Output:
// Start
// End
// Promise
// Timeout
5. Memory Management
Garbage Collection
// Reference Counting
let obj = { data: "some data" };
obj = null; // Object becomes eligible for GC
// Mark and Sweep
function process() {
const temp = { x: 123 };
// temp is only reachable within this function
} // temp becomes eligible for GC
Memory Leaks
// 1. Global Variables
window.globalData = { /* large data */ };
// 2. Forgotten Timers
setInterval(() => {
const data = { /* large data */ };
}, 1000);
// 3. Closures
function createLeak() {
const largeData = { /* large data */ };
return () => console.log(largeData);
}
6. Error Handling
Error Propagation
try {
throw new Error('Something went wrong');
} catch (error) {
console.error(error);
} finally {
console.log('Cleanup');
}
// Async Error Handling
async function fetchData() {
try {
const response = await fetch('api/data');
return await response.json();
} catch (error) {
console.error('Fetch error:', error);
}
}
7. Browser APIs and Web APIs
DOM Manipulation
// Batched DOM Updates
requestAnimationFrame(() => {
element.style.transform = 'translateX(100px)';
});
// MutationObserver
const observer = new MutationObserver(mutations => {
console.log('DOM changed');
});
observer.observe(document.body, {
childList: true,
subtree: true
});
Event Handling
// Event Bubbling
document.body.addEventListener('click', function(event) {
console.log('Body clicked');
}, false);
// Event Capturing
document.body.addEventListener('click', function(event) {
console.log('Capture phase');
}, true);
8. Performance Optimization
Critical Rendering Path
// Optimize loading
document.addEventListener('DOMContentLoaded', () => {
// DOM is ready
});
window.addEventListener('load', () => {
// Everything is loaded
});
// Avoid layout thrashing
const height = element.offsetHeight; // Read
element.style.height = height + 100 + 'px'; // Write
Code Splitting
// Dynamic Import
button.addEventListener('click', async () => {
const module = await import('./feature.js');
module.doSomething();
});
9. Debugging Tips
Console Methods
// Performance Measurement
console.time('operation');
// ... some operations
console.timeEnd('operation');
// Stack Trace
console.trace('Trace message');
// Memory Snapshot
console.memory
Source Maps
// Enable source maps
{
"version": 3,
"sources": ["original.js"],
"names": ["add", "a", "b"],
"mappings": "AAAA,SAASA,IAAIC,EAAGC"
}
10. Common Pitfalls and Solutions
Performance Issues
// Bad
for (let i = 0; i < array.length; i++) {}
// Good
const length = array.length;
for (let i = 0; i < length; i++) {}
// Better
array.forEach(item => {});
Memory Management
// Bad - Memory Leak
class Component {
constructor() {
this.listener = () => this.update();
window.addEventListener('resize', this.listener);
}
}
// Good - Cleanup
class Component {
constructor() {
this.listener = () => this.update();
window.addEventListener('resize', this.listener);
}
destroy() {
window.removeEventListener('resize', this.listener);
}
}
JavaScript Engine Execution Process
1. Engine Components
Main Components
// JavaScript Engine Architecture
┌───────────────────────────────── ────┐
│ JavaScript Engine (e.g., V8) │
├─────────────────────────────────────┤
│ Parser → AST → Interpreter (Ignition)│
│ ↓ │
│ Compiler (TurboFan) │
└─────────────────────────────────────┘
2. Parsing Phase
Lexical Analysis (Tokenization)
// Source Code
function sum(a, b) { return a + b; }
// Tokens
[
{ type: 'keyword', value: 'function' },
{ type: 'identifier', value: 'sum' },
{ type: 'punctuation', value: '(' },
{ type: 'identifier', value: 'a' },
{ type: 'punctuation', value: ',' },
{ type: 'identifier', value: 'b' },
{ type: 'punctuation', value: ')' },
{ type: 'punctuation', value: '{' },
{ type: 'keyword', value: 'return' },
{ type: 'identifier', value: 'a' },
{ type: 'operator', value: '+' },
{ type: 'identifier', value: 'b' },
{ type: 'punctuation', value: ';' },
{ type: 'punctuation', value: '}' }
]
Abstract Syntax Tree (AST)
// AST Structure
{
"type": "Program",
"body": [{
"type": "FunctionDeclaration",
"id": {
"type": "Identifier",
"name": "sum"
},
"params": [
{
"type": "Identifier",
"name": "a"
},
{
"type": "Identifier",
"name": "b"
}
],
"body": {
"type": "BlockStatement",
"body": [{
"type": "ReturnStatement",
"argument": {
"type": "BinaryExpression",
"operator": "+",
"left": {
"type": "Identifier",
"name": "a"
},
"right": {
"type": "Identifier",
"name": "b"
}
}
}]
}
}]
}
3. Compilation Pipeline
Interpreter (Ignition in V8)
// Bytecode Generation
function example() {
let x = 1;
x += 2;
return x;
}
// Simplified Bytecode
LdaZero // Load accumulator with 0
Star r0 // Store accumulator to register 0
LdaSmi #1 // Load small integer 1
Add r0 // Add register 0 to accumulator
Return // Return accumulator
JIT Compilation (TurboFan in V8)
// Hot Function Detection
function hotFunction(a, b) {
return a + b; // Called many times
}
// Optimization Tiers
// Tier 1: Interpreted
// Tier 2: Baseline compiled
// Tier 3: Optimized machine code
4. Memory Management
Memory Spaces
// Memory Layout
┌─────────────────┐
│ Code Space │ // Executable code
├─────────────────┤
│ New Space │ // Young objects
├─────────────────┤
│ Old Space │ // Long-lived objects
├─────────────────┤
│ Large Object │ // Objects > 1MB
└─────────────────┘
Garbage Collection Process
// Mark and Sweep Algorithm
function createObjects() {
let obj1 = { name: 'obj1' };
let obj2 = { name: 'obj2' };
obj1.ref = obj2; // Create reference
obj2 = null; // Break reference
return obj1; // obj2 eligible for GC
}
// Generation-based Collection
// Young Generation (Minor GC)
// Old Generation (Major GC)
5. Execution Context
Context Creation
// Global Execution Context
GlobalExecutionContext = {
ThisBinding: window, // or global
VariableEnvironment: { /* variables */ },
LexicalEnvironment: { /* let/const */ }
}
// Function Execution Context
FunctionExecutionContext = {
ThisBinding: <determined by call>,
VariableEnvironment: { /* variables */ },
LexicalEnvironment: { /* let/const */ }
}
Scope Chain
function outer() {
const a = 1;
function inner() {
const b = 2;
console.log(a, b);
}
inner();
}
// Scope Chain: inner → outer → global
6. Optimization Techniques
Inline Caching
// Before Optimization
function getProperty(obj, prop) {
return obj[prop];
}
// After Inline Caching
// Engine caches the location of prop
// for subsequent lookups
Hidden Classes
// Bad for optimization
function Point(x, y) {
this.x = x;
this.y = y;
}
let p1 = new Point(1, 2);
p1.z = 3; // Creates new hidden class
// Good for optimization
function Point(x, y) {
this.x = x;
this.y = y;
this.z = undefined; // Declare all properties upfront
}
7. Performance Monitoring
Profiling
// CPU Profiling
console.profile('MyProfile');
// ... code to profile
console.profileEnd('MyProfile');
// Memory Profiling
const heap = process.memoryUsage();
console.log(heap);
8. Common Optimizations
Function Inlining
// Before Inlining
function add(a, b) {
return a + b;
}
let result = add(1, 2);
// After Inlining (Internal)
let result = 1 + 2; // Function call removed
Deoptimization
function add(a, b) {
// Optimized for numbers
return a + b;
}
add(1, 2); // Optimized
add("1", "2"); // Deoptimized due to type change
9. Engine-specific Features (V8)
Turbofan Optimizations
// Type Specialization
function add(a, b) {
return a + b;
}
// After many number-only calls
// Engine creates specialized version for numbers
Orinoco Garbage Collector
// Concurrent Marking
// Incremental Marking
// Lazy Sweeping
// Parallel Scavenging