Web Fundamentals

JavaScript (JS)

A detailed guide to the V8 engine runtime, event loops, execution contexts, closures, prototypes, asynchronous programming, and performance.

1. V8 Engine Runtime & Compilation

Computers do not understand JavaScript text directly. The V8 engine acts as a translation team to convert code text into raw CPU commands.

  • Analogy: The dynamic translation team.
  JS Code ──► Parser ──► AST (Abstract Syntax Tree) ──► Ignition (Interpreter)
                                                           │ (Bytecode)

                                                       TurboFan (JIT Compiler)
                                                           │ (Native Machine Code)

                                                          CPU
  • The Parser: Reads the text characters of your code and builds a structured map called the Abstract Syntax Tree (AST).
  • The Interpreter (Ignition): A quick translator who translates the AST into bytecode instantly. It starts running code immediately, but executes it slowly.
  • The JIT Compiler (TurboFan): A speed specialist. They watch for code loops that run 1000 times (hot spots), compile them directly into raw copper-wire CPU instructions (native machine code), and bypass the interpreter to run them at lightning speed.

2. Call Stack & The Event Loop

JavaScript is single-threaded, meaning it can only perform one task at a time.

  • Analogy: A single-chef kitchen with a helper reservation window.
   [ Call Stack ] ──► (Async Web API Call) ──► [ Web APIs (Helper) ]
          ▲                                           │
          │                                           ▼
      (Event Loop) ◄── [ Microtasks (VIP) ] ◄──── (Completes)


      (Event Loop) ◄── [ Macrotasks (Queue) ] ◄── (Completes)
  • Call Stack: The chef's immediate order ticket stack. The chef only works on the top ticket (Last In, First Out).
  • Web APIs: The kitchen's smart automated helpers (e.g. browser timers, fetch requests). While the helper is waiting for the timer to expire, the chef continues cooking.
  • Callback Queue (Macrotasks): A line of completed helper tickets (e.g., click events, timeouts) waiting for the chef.
  • Microtask Queue: VIP hot-line tickets (e.g., Promises, .then() handlers).
  • Event Loop: The kitchen manager. They wait until the chef's immediate ticket stack (Call Stack) is completely empty. Then, they first check the VIP microtask queue and run all those tickets. Finally, they take the next macrotask ticket from the callback queue and hand it to the chef.
console.log("Start"); // 1. Run immediately on Stack

setTimeout(() => {
  console.log("Timeout"); // 4. Queued to Macrotasks
}, 0);

Promise.resolve().then(() => {
  console.log("Promise"); // 3. Queued to VIP Microtasks
});

console.log("End"); // 2. Run immediately on Stack

// Output Order: "Start" -> "End" -> "Promise" -> "Timeout"

3. Scopes, Hoisting & Closures

Scopes & Hoisting: Setting Up the Stage

  • Hoisting: Setting up props on a theatrical stage before the actors begin reading the script.
    • var is declared and assigned undefined on the stage floor.
    • let and const are placed inside a locked glass cabinet (Temporal Dead Zone) until the actor reaches the line that unlocks them.

Closures: The Apartment Wiretap

  • Closure: A spy leaving a wiretap bug in an apartment.
  • Analogy: When a function finishes running, its local variables (the apartment) are usually cleaned up by garbage collection. But if that function returns an inner function that references those variables, it creates a closure. The inner function acts as a wiretap that remains in the apartment, keeping the memory alive so it can still read the variables long after the parent function has exited.
function createCounter() {
  let count = 0; // Stays alive in the apartment
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // Prints: 1
console.log(counter()); // Prints: 2

4. Dynamic Binding: this, call, apply, bind

The this keyword refers to the object that is executing the current function.

  • Analogy: "Who owns the current phone?" If a phone rings, this refers to whoever is holding the phone at that exact moment.
    • Implicit: When a method is called on an object, that object is holding the phone (user.sayName()).
    • Arrow Functions: Arrow functions are like a phone that has no owner; they simply inherit the ownership (lexical scope) of the room they were built in.
const person = {
  name: "Kamran",
  greetNormal: function() {
    console.log("Hello, " + this.name); // 'this' points to person
  },
  greetArrow: () => {
    console.log("Hello, " + this.name); // 'this' inherits outer window scope (name is undefined)
  }
};
  • call(thisArg, arg1, arg2): Invokes the function immediately, manually handing the phone to thisArg.
  • apply(thisArg, [argsArray]): Same as call, but arguments are passed as an array.
  • bind(thisArg): Returns a new function with the phone permanently glued to thisArg.

5. Conceptual Quizzes

Knowledge Check

What is the execution order of the logs: console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D');?

Knowledge Check

What is the Temporal Dead Zone in JavaScript?


6. Practice Problems

Problem 1: Custom Promise Implementation

Write a basic constructor SimplePromise that:

  1. Supports state transitions from PENDING to RESOLVED or REJECTED.
  2. Supports chaining using .then(onResolve).

On this page