← Back to all projects

LEARN JAVASCRIPT DEEP DIVE

JavaScript is the lingua franca of the web. It started as a toy language for animating buttons in 1995 (created in 10 days by Brendan Eich) and has evolved into the most ubiquitous runtime environment in the world. It powers everything from microcontrollers to massive cloud infrastructure (Node.js/Deno/Bun).

Learn JavaScript: From Zero to Engine Internals Master

Goal: Deeply understand JavaScript not just as a tool for interaction, but as a system of execution contexts, prototype chains, and event loops. You will move from “using” libraries to understanding the engine mechanics that power them, mastering closures, asynchronous patterns, and the prototypal object model from first principles.


Why JavaScript Matters

JavaScript is the lingua franca of the web. It started as a toy language for animating buttons in 1995 (created in 10 days by Brendan Eich) and has evolved into the most ubiquitous runtime environment in the world. It powers everything from microcontrollers to massive cloud infrastructure (Node.js/Deno/Bun).

Understanding JavaScript deeply means you stop fighting the language. You stop guessing why this is undefined, why the UI froze, or why your loop finished before your API call. You gain the power to write libraries, performance tools, and complex systems that work with the engine, not against it.


Core Concept Analysis

To master JS, you must visualize what the engine (V8, SpiderMonkey, JavaScriptCore) is actually doing.

1. The Execution Context Stack (The “Call Stack”)

Everything in JS happens inside an Execution Context. It’s the environment where code runs.

   YOUR CODE                 THE ENGINE'S STACK
   ─────────                 ──────────────────

   function b() {            ┌─────────────┐
     console.log('hi');      │   b()       │  <── Active context
   }                         ├─────────────┤
                             │   a()       │  <── Paused
   function a() {            ├─────────────┤
     b();                    │ Global (GEC)│  <── Bottom of stack
   }                         └─────────────┘

   a();

Key Takeaway: JS is single-threaded. It can only do one thing at a time. The stack records where we are. If the stack is blocked (e.g., while(true)), the browser freezes.

2. The Scope Chain (Lexical Environment)

Scopes are determined at write time (lexical), not run time. Inner functions have access to variables in their outer definitions.

   ┌── Global Scope ──────────────────────────┐
   │  let x = 10;                             │
   │                                          │
   │  ┌── Function outer() ────────────────┐  │
   │  │  let y = 20;                       │  │
   │  │                                    │  │
   │  │  ┌── Function inner() ──────────┐  │  │
   │  │  │  console.log(x + y);         │  │  │
   │  │  │  // Looks up ↑ then ↑        │  │  │
   │  │  └──────────────────────────────┘  │  │
   │  └────────────────────────────────────┘  │
   └──────────────────────────────────────────┘

Key Takeaway: Closures are simply functions that remember the scope in which they were created, even after that scope has “returned” or popped off the stack.

3. The Event Loop & Task Queues

How does single-threaded JS handle async operations like fetch or setTimeout? It cheats by offloading work to the browser/environment.

   ┌──────────────┐         ┌──────────────┐
   │  Call Stack  │         │  Web APIs    │
   │              │         │ (Browser)    │
   │   (empty)    │         │              │
   └──────▲───────┘         │ Timer done!  │
          │                 └──────┬───────┘
          │ (Event Loop)           │
          │ Checks if stack        ▼
          │ is empty        ┌──────────────┐
          └─────────────────┤ Callback     │
                            │ Queue        │
                            │ [callback]   │
                            └──────────────┘

The Rule: The Event Loop pushes the first item from the Callback Queue to the Call Stack only when the Call Stack is empty.

4. The Prototype Chain

JavaScript doesn’t have classes (class is syntax sugar). It has objects linked to other objects.

   obj.toString()
       │
       ▼
   Does 'obj' have it?  ─── NO ──┐
                                 │
   Does obj.__proto__            │ (Prototype Link)
   (Object.prototype)            ▼
   have it? ───────────────►  YES! Execute it.

Key Takeaway: Inheritance is just a delegation chain. You can change these links at runtime (though you probably shouldn’t).

5. The “this” Keyword (Binding)

this is not about where a function is declared, but how it is called. It is a runtime binding.

   const obj = {
     name: 'Alice',
     greet: function() { console.log(this.name); }
   };

   obj.greet();          // 1. Method call: this = obj
   const g = obj.greet;
   g();                  // 2. Plain call: this = global/undefined
   g.call({name: 'Bob'}) // 3. Explicit call: this = {name: 'Bob'}
   new g();              // 4. Constructor call: this = new instance

Key Takeaway: There are 4 rules for this binding: Default, Implicit, Explicit (call/apply/bind), and new. Arrow functions ignore all of these and use the this from their lexical scope.


Concept Summary Table

Concept Cluster What You Need to Internalize
Execution Context The “environment” a function runs in. Created when a function is called. Contains the Scope Chain, Variable Object, and this.
Closures A function + its lexical scope. Data is preserved (“closed over”) even after the outer function finishes execution.
The Event Loop The mechanism that coordinates the synchronous Call Stack and asynchronous Task Queues. It prevents blocking.
Micro vs Macro Tasks Promises (Micro) have higher priority than setTimeout (Macro). The microtask queue must be empty before the next macrotask runs.
Prototypes Objects inherit directly from other objects via a hidden link ([[Prototype]]). Classes are just syntax sugar over this.
this Binding this is defined by how a function is called (call site), not where it is defined (unless using arrow functions).

Deep Dive Reading by Concept

Core Mechanics & Scopes

Concept Book & Chapter
Scopes & Closures “You Don’t Know JS Yet: Scope & Closures” by Kyle Simpson — Ch. 1-5
Lexical Scope “JavaScript: The Definitive Guide” by David Flanagan — Ch. 8 (Functions)

Async & Event Loop

Concept Book & Chapter
Async Patterns “Eloquent JavaScript” by Marijn Haverbeke — Ch. 11 (Asynchronous Programming)
Event Loop “High Performance Browser Networking” by Ilya Grigorik — Ch. 1 (Primer on Latency/Bandwidth) & MDN Concurrency Model

Objects & Prototypes

Concept Book & Chapter
Prototypes “You Don’t Know JS Yet: Objects & Classes” by Kyle Simpson — Ch. 4-6
Classes vs Prototypes “JavaScript: The Good Parts” by Douglas Crockford — Ch. 3 (Objects) & Ch. 4 (Functions)

Essential Reading Order

  1. Foundation: “You Don’t Know JS: Scope & Closures” (Understand variable lifecycle).
  2. Mechanics: “You Don’t Know JS: Objects & Classes” (Understand the object model).
  3. Async: “Eloquent JavaScript” Ch. 11 (Understand the event loop).

Project List

Project 1: The “Lodash” Rebuild (Method Implementation)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript (Vanilla)
  • Alternative Programming Languages: TypeScript
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold” (Shows mastery of fundamentals)
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Functional Programming / Array Methods
  • Software or Tool: Jest/Mocha (for testing your implementations)
  • Main Book: “JavaScript: The Definitive Guide” by David Flanagan

What you’ll build: A utility library (like Lodash or Underscore) built from scratch. You will manually implement map, reduce, filter, find, bind, throttle, and debounce adding them to a custom object or directly to Array.prototype (for educational purposes only).

Why it teaches Callbacks & HOF: You cannot simply use map; you must build the engine that calls the user’s function. You will deal with this context, handling indices, and efficiently iterating. bind, call, and apply implementations force you to understand function context.

Core challenges you’ll face:

  • Context Loss: Implementing myBind requires handling what this refers to when the function finally runs.
  • Callback Signature: Ensuring your map passes (item, index, array) correctly.
  • Timing Control: debounce and throttle require mastering closures and setTimeout state.

Key Concepts:

  • Higher-Order Functions: Functions that take functions as args or return them.
  • this Keyword: How it changes based on invocation.
  • Closures: debounce relies entirely on a closure to hold the timer ID.

Difficulty: Beginner/Intermediate Time estimate: Weekend Prerequisites: Basic syntax, understanding of functions.


Real World Outcome

You will create a library file myUtils.js and a test file test.js. Running the tests will prove your implementation works exactly like the native methods.

Example Output:

$ node test.js

[PASS] myMap: transforms [1, 2, 3] to [2, 4, 6]
[PASS] myFilter: keeps only evens from [1, 2, 3, 4]
[PASS] myReduce: sums [1, 2, 3, 4] to 10
[PASS] myBind: binds 'this' context correctly to user object
[PASS] myDebounce: only executes once after 100ms delay

All 5 tests passed!

The Core Question You’re Answering

“How do functions like map and bind actually work under the hood?”

Before coding, realize that map isn’t magic. It’s a for loop that calls a function. bind isn’t magic. It’s a function that returns another function using apply.

Concepts You Must Understand First

Stop and research these before coding:

  1. Higher-Order Functions
    • What makes a function “higher-order”?
    • How do you pass a function as an argument?
    • Book Reference: “Eloquent JavaScript” Ch. 5 - Marijn Haverbeke
  2. The this Keyword
    • What determines the value of this?
    • How does .apply() change this?
    • Why do we need to save this (or use arrow functions) in closures?
    • Book Reference: “You Don’t Know JS Yet: Objects & Classes” Ch. 2 - Kyle Simpson
  3. Closures for State
    • How can a function “remember” a variable (like a timer ID) after it returns?
    • Book Reference: “You Don’t Know JS Yet: Scope & Closures” Ch. 5 - Kyle Simpson

Questions to Guide Your Design

Before implementing, think through these:

  1. Implementing map
    • How do you create the result array?
    • What arguments does the callback need? (element, index, array)
    • How do you handle sparse arrays? (Optional, but good to think about)
  2. Implementing bind
    • bind returns a new function. What does that new function do when called?
    • How do you pass arguments from the bind call and the execution call? (Partial application)
  3. Implementing debounce
    • Where do you store the timeoutId?
    • What should happen if the function is called again before the timeout clears?

Thinking Exercise

Trace bind

function myBind(fn, context) {
  return function() {
    fn.apply(context);
  }
}

Questions while tracing:

  • Does this handle arguments passed to the bound function?
  • Does this handle arguments passed to myBind (partial application)?
  • What happens if fn uses this?

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “Implement Array.prototype.map polyfill.”
  2. “What is the difference between call, apply, and bind?”
  3. “Implement a debounce function.”
  4. “Why is this undefined in my callback?”
  5. “What is a closure and give a practical example?”

Hints in Layers

Hint 1: Map Structure Create a loop. Inside the loop, call the callback fn(arr[i], i, arr). Push the result to a new array.

Hint 2: Bind Arguments Use ...args in the definition of myBind to capture initial arguments. Return a function that takes ...moreArgs. Combine them when calling apply.

Hint 3: Debounce Timer You need a variable let timeout; outside the returned function. Inside, call clearTimeout(timeout) then timeout = setTimeout(...).

Books That Will Help

Topic Book Chapter
Functional Patterns “Eloquent JavaScript” Ch. 5 (Higher-Order Functions)
this & Prototypes “You Don’t Know JS: Objects & Classes” Ch. 2 (this All Makes Sense Now)

Project 2: The Event Loop Visualizer (CLI)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript (Node.js)
  • Alternative Programming Languages: None (Strictly JS concept)
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Async / Event Loop
  • Software or Tool: Node.js process API
  • Main Book: “Node.js Design Patterns” by Mario Casciaro

What you’ll build: A CLI tool that simulates the JavaScript Event Loop. You’ll create a “Task Runner” that accepts “sync” code, “timeouts”, and “microtasks” (promises), and executes them in the exact order a real JS engine would, logging the state of the Call Stack, Macro Queue, and Micro Queue at each step.

Why it teaches the Event Loop: You will implement the priority logic yourself. You’ll have to code the rule: “Run all microtasks before the next macrotask.” This cements the execution order in your brain forever.

Core challenges you’ll face:

  • Queue Priority: Implementing two distinct queues (Task vs Microtask) and managing their execution order.
  • Blocking Simulation: Representing synchronous code execution that blocks the loop.
  • Loop Logic: Creating the while(true) loop that checks queues only when the stack is empty.

Key Concepts:

  • Call Stack: LIFO structure.
  • Macrotasks: setTimeout, setInterval, I/O.
  • Microtasks: Promise.then, queueMicrotask.
  • Run-to-completion: Code in the stack runs until finished.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Basic Promise knowledge, understanding of queues/stacks.


Real World Outcome

You will run a script eventLoopSim.js that prints a log.

Example Output:

$ node eventLoopSim.js

[Stack] Executing main()
[Stack] Executing console.log('Start')
Start
[WebAPI] setTimeout(0) -> Timer started
[Micro] Promise.resolve().then() -> Added to Microtask Queue
[Stack] Executing console.log('End')
End

--- Sync Code Done ---
--- Event Loop Tick ---

[Stack] Empty. Checking Microtasks...
[Micro] Found 1 task.
[Stack] Executing Promise callback...
Promise Resolved
[Stack] Empty. Microtasks Empty. Checking Macrotasks...
[Macro] Found 1 task.
[Stack] Executing setTimeout callback...
Timeout

The Core Question You’re Answering

“Why does a 0ms timeout not run immediately?”

Concepts You Must Understand First

Stop and research these before coding:

  1. The Call Stack
    • What happens to the stack when a function returns?
    • How does JS know where to return to?
    • Book Reference: “Node.js Design Patterns” Ch. 1
  2. Task Queues
    • What is the difference between the Task Queue (Macrotasks) and the Microtask Queue?
    • Which queue does process.nextTick go to in Node.js?
    • Book Reference: “You Don’t Know JS: Async & Performance” Ch. 1

Questions to Guide Your Design

Before implementing, think through these:

  1. Queue Implementation
    • How will you store the tasks? (Arrays are fine).
    • How do you differentiate between a sync task and an async task in your simulator?
  2. The “Tick”
    • How do you simulate the engine checking the stack? (A while loop that runs as long as there are queues).
  3. Starvation
    • What happens if you keep adding microtasks? Does the macrotask ever run?

Thinking Exercise

Trace Execution Order

console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'))
       .then(() => console.log('4'));
console.log('5');

Questions while tracing:

  • What prints first, 1 or 5?
  • When does ‘2’ print?
  • Does ‘4’ print before or after ‘2’? Why?

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “What is the output of this async code snippet?” (Very common)
  2. “Explain the difference between Macrotasks and Microtasks.”
  3. “Does setTimeout(fn, 0) run immediately?”
  4. “What is the Event Loop?”

Hints in Layers

Hint 1: Class Structure Create a class EventLoop with callStack, macroTaskQueue, and microTaskQueue.

Hint 2: Execution Method Create a run() method. It should loop while any queue has items. Inside loop:

  1. If stack not empty, run stack item.
  2. Else if microQueue not empty, move ONE item to stack.
  3. Else if macroQueue not empty, move ONE item to stack.

Hint 3: Priority Make sure your loop logic always drains the microTaskQueue before checking the macroTaskQueue.

Books That Will Help

Topic Book Chapter
Event Loop “Node.js Design Patterns” Ch. 1 (The Node.js Platform)
Async “You Don’t Know JS: Async & Performance” Ch. 1 (Asynchrony: Now & Later)

Project 3: A Custom Promise Implementation (From Scratch)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript
  • Alternative Programming Languages: TypeScript
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Asynchronous State Machines
  • Software or Tool: None (Vanilla JS)
  • Main Book: “You Don’t Know JS: Async & Performance” by Kyle Simpson

What you’ll build: A fully compliant Promise class (basically a “MyPromise”). It must handle:

  1. Three states: PENDING, FULFILLED, REJECTED.
  2. .then() chaining (returning a new MyPromise).
  3. Asynchronous execution of handlers (even if resolved immediately).
  4. Error bubbling through chains.

Why it teaches Async Internals: You realize Promises aren’t magic. They are just objects with a state machine and a list of callback functions. You will understand exactly why catch works and how values propagate down a chain.

Core challenges you’ll face:

  • Chaining: .then() must return a new Promise. If the handler returns a value, the new Promise resolves with it. If it returns a Promise, the new Promise must wait for it.
  • Asynchronity: Use queueMicrotask (or setTimeout) to ensure handlers run after the synchronous code, honoring the spec.
  • State Immutability: Once resolved, state cannot change.

Key Concepts:

  • State Machine: Transitions are one-way.
  • Microtask Queue: Why we use queueMicrotask.
  • Value Propagation: Passing results from one .then to the next.

Difficulty: Advanced Time estimate: 1 week Prerequisites: Solid understanding of callbacks and this.


Real World Outcome

You will run the official Promises/A+ Compliance Test Suite (872 tests) against your library.

Example Output:

$ npm test

  872 passing (12s)
  0 failing

If you pass this, your MyPromise behaves exactly like native Promise.

The Core Question You’re Answering

“How does a Promise ‘pause’ execution without blocking the main thread?”

Concepts You Must Understand First

Stop and research these before coding:

  1. Inversion of Control
    • Why are callbacks “trust issues”?
    • Book Reference: “You Don’t Know JS: Async & Performance” Ch. 2
  2. Microtasks
    • Why must .then callbacks run asynchronously even if the promise is already resolved?
    • Book Reference: “You Don’t Know JS: Async & Performance” Ch. 3

Questions to Guide Your Design

  1. State Management
    • How do you ensure state can only transition once? (if (state !== PENDING) return)
  2. Callback Storage
    • If then() is called on a PENDING promise, where do you put the callback?

Thinking Exercise

Trace:

const p = new MyPromise(resolve => resolve(1));
p.then(v => {
  console.log(v);
  return new MyPromise(r => setTimeout(() => r(2), 100));
}).then(v => console.log(v));

The Interview Questions They’ll Ask

  1. “What happens if you resolve a Promise with itself?”
  2. “Implement Promise.all and Promise.race.”
  3. “Why is catch just syntax sugar for then?”

Hints in Layers

Hint 1: Constructor takes an executor(resolve, reject). resolve changes state to FULFILLED and stores the value. Hint 2: .then(onSuccess) checks state. If PENDING, push onSuccess to a callbacks array. If FULFILLED, run onSuccess immediately (wrapped in microtask). Hint 3: The tricky part: The resolve function must check if the value passed to it is a “thenable” (has a .then method). If so, it must subscribe to it.

Books That Will Help

Topic Book Chapter
Promise Internals “You Don’t Know JS: Async & Performance” Ch. 3 (Promises)

Project 4: Reactive State System (Proxy & Signals)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript
  • Alternative Programming Languages: TypeScript
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 5. The “Industry Disruptor” (Basis of frontend frameworks)
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Metaprogramming / Proxies
  • Software or Tool: Vanilla JS
  • Main Book: “Metaprogramming in JavaScript” (various online resources/MDN)

What you’ll build: A reactive engine similar to Vue 3’s Reactivity system or MobX. You will create a function reactive(obj) that returns a proxy. When you read a property, it tracks the dependency. When you write to it, it triggers all functions (effects) that depend on it.

Why it teaches Proxies & Closures: This is the modern way JS frameworks work. You’ll learn Proxy traps (get, set) and how to maintain a global “active effect” using closures to link data to DOM updates automatically.

Core challenges you’ll face:

  • Dependency Tracking: How do I know which function is currently reading a property? (Hint: Global variable pattern).
  • Proxy Traps: Intercepting every read/write without infinite loops.
  • Nested Objects: Making deep properties reactive.

Key Concepts:

  • Proxy & Reflect: Intercepting fundamental language operations.
  • The Observer Pattern: Publishers (data) and Subscribers (effects).
  • WeakMap: Storing dependencies without causing memory leaks.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Understanding of Objects and Reference types.


Real World Outcome

You will create a mini-library where changing data updates the HTML automatically.

Example Output: Open index.html.

  1. See Count: 0.
  2. Open console, type state.count++.
  3. The DOM updates to Count: 1 instantly.

The Core Question You’re Answering

“How do modern frameworks (Vue, Solid, MobX) know when to re-render?”

Concepts You Must Understand First

  1. Proxy
    • How to intercept get and set?
    • Book Reference: “Deep JavaScript” (online) - Proxies
  2. Dependency Graph
    • What is a Subscriber/Publisher pattern?

Questions to Guide Your Design

  1. Automatic Registration
    • How do we know who is asking for state.count? (The global activeEffect trick).
  2. Memory Management
    • Why use WeakMap for the dependency storage?

Thinking Exercise

Trace: effect(() => console.log(state.a + state.b))

  1. effect starts. Sets active.
  2. state.a getter triggers. Adds active to a’s subscribers.
  3. state.b getter triggers. Adds active to b’s subscribers.
  4. effect ends. Clears active.

The Interview Questions They’ll Ask

  1. “What is a Proxy in JavaScript?”
  2. “Explain the difference between Object.defineProperty (Vue 2) and Proxy (Vue 3).”
  3. “How would you prevent memory leaks in a listener system?” (Answer: WeakMap).

Hints in Layers

Hint 1: Global State Create a global variable let activeEffect = null. This will hold the function currently running.

Hint 2: The Effect Function Your effect(fn) function should set activeEffect = fn, call fn(), then set activeEffect = null.

Hint 3: Dependency Storage Use a WeakMap to store dependencies. target -> key -> Set(effects).

Hint 4: The Proxy In the get trap: if activeEffect is set, look up the Set for this target/key and add the effect. In the set trap: look up the Set and run every effect in it.

Books That Will Help

Topic Book Chapter
Metaprogramming “Deep JavaScript” (Axel Rauschmayer) Ch. on Proxies
Observer Pattern “Learning JavaScript Design Patterns” Ch. Observer

Project 5: The “Retro” Class System (Prototypal Inheritance)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript
  • Alternative Programming Languages: None
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Object Model / Prototypes
  • Software or Tool: Vanilla JS
  • Main Book: “You Don’t Know JS: Objects & Classes”

What you’ll build: A “Class” function generator (like dojo.declare or Backbone.extend from the old days) that mimics ES6 class behavior using only prototypes. You will implement inheritance (extend), super calls, and static properties without using the class keyword.

Why it teaches Prototypes: ES6 classes are sugar. To really know JS, you must build the sugar. You will manually link __proto__, use Object.create, and understand the “Constructor Function” pattern that powered the web for 20 years.

Core challenges you’ll face:

  • Prototype Chain Linking: Ensuring Child.prototype delegates to Parent.prototype.
  • Constructor Stealing: Calling Parent.call(this) inside the Child constructor.
  • Super Calls: How to let a child method call the parent method.

Key Concepts:

  • __proto__ vs prototype: The classic interview stumbling block.
  • new Operator: What it actually does (creates obj, links proto, binds this, returns obj).
  • Delegation: Objects delegating failed lookups up the chain.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Understanding of objects and functions.


Real World Outcome

You will create a library class.js that allows Java-like class definitions.

Example Output:

const Animal = Class.extend({
  init: function(name) { this.name = name; },
  speak: function() { return "I am " + this.name; }
});

const Dog = Animal.extend({
  speak: function() {
    // "super" call logic
    return this._super() + " and I bark!";
  }
});

const d = new Dog("Rex");
console.log(d.speak()); // "I am Rex and I bark!"
console.log(d instanceof Animal); // true

The Core Question You’re Answering

“What actually happens when I type class Dog extends Animal?”

Concepts You Must Understand First

Stop and research these before coding:

  1. Constructor Functions
    • What happens when a function is called with new?
    • Book Reference: “You Don’t Know JS: Objects & Classes” Ch. 4
  2. Object.create()
    • How does it link objects without running constructors?
    • Book Reference: “You Don’t Know JS: Objects & Classes” Ch. 5

Questions to Guide Your Design

  1. Linking Prototypes
    • How do you ensure Dog.prototype inherits from Animal.prototype but doesn’t share the same object?
  2. The Constructor Property
    • How do you repair the .constructor property after linking prototypes?

Thinking Exercise

Trace new Dog()

  1. new creates empty object.
  2. Links __proto__ to Dog.prototype.
  3. Calls Dog.init.
  4. Dog.init calls this._super (Animal.init).
  5. Properties set on this.

The Interview Questions They’ll Ask

  1. “Explain prototypal inheritance.”
  2. “What does new do? (Step by step)”
  3. “How do you implement inheritance in ES5?”

Hints in Layers

Hint 1: Extend Function The extend function should return a new constructor function that calls init.

Hint 2: Inheritance Set NewConstructor.prototype = Object.create(Parent.prototype).

Hint 3: Repair Constructor Reset NewConstructor.prototype.constructor = NewConstructor.

Hint 4: Super Magic Wrap methods. If a child method calls _super, temporarily swap this._super to point to the parent’s method, run the child method, then swap it back.

Books That Will Help

Topic Book Chapter
Prototypes “You Don’t Know JS: Objects & Classes” Ch. 5 (Prototypes)

Project 6: A Tiny JS Interpreter (AST Walker)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript
  • Alternative Programming Languages: TypeScript
  • Coolness Level: Level 5: Pure Magic
  • Business Potential: 5. The “Industry Disruptor” (Babel/SWC started here)
  • Difficulty: Level 5: Master
  • Knowledge Area: Compilers / ASTs
  • Software or Tool: Acorn (parser) or hand-written parser
  • Main Book: “Structure and Interpretation of Computer Programs” (JS Edition)

What you’ll build: A program that takes a string of JavaScript code (const x = 10 + 5;), parses it into an AST (Abstract Syntax Tree), and then executes it node-by-node. You will effectively write a JS engine inside JS.

Why it teaches Execution Contexts: You have to manually implement the “Environment” (Execution Context). You’ll need a way to store variables, look them up in parent scopes, and throw errors if they don’t exist. This is what the engine does.

Core challenges you’ll face:

  • Scope Management: Implementing nested environments where outer variables are accessible but inner ones are not.
  • AST Traversal: Writing a recursive evaluate(node) function.
  • Variable Declaration: Handling const vs let (if you choose to support re-assignment rules).

Key Concepts:

  • Abstract Syntax Trees (AST): Tree representation of code.
  • Lexical Environment: Key-value storage for variables.
  • Recursive Descent: How interpreters walk the tree.

Difficulty: Master Time estimate: 1 month+ Prerequisites: Recursion, Data Structures (Trees).


Real World Outcome

You will run a file interpreter.js that executes JS source string.

Example Output:

const interpreter = new TinyJS();

const code = `
  const x = 10;
  const y = 20;
  function add(a, b) {
    return a + b;
  }
  add(x, y);
`;

const result = interpreter.run(code);
console.log(result); // 30

The Core Question You’re Answering

“How does text become behavior?”

Concepts You Must Understand First

  1. ASTs
    • Use astexplorer.net to see what code looks like as a tree.
    • Book Reference: “Structure and Interpretation of Computer Programs” Ch. 4
  2. Visitors Pattern
    • Separating the algorithm from the object structure.

Questions to Guide Your Design

  1. Function Calls
    • How do I represent a “Function Call”? (Creating a new environment with arguments bound to parameters).
  2. Return Statements
    • How do I handle return deep inside a recursive evaluation? (Throwing a special Return value? Returning a wrapped object?).

Thinking Exercise

Trace Evaluation

Code: x + 1 with Env {x: 10}.

  1. evaluate(BinaryExpression)
  2. evaluate(Identifier x) -> Lookup Env -> 10.
  3. evaluate(Literal 1) -> 1.
  4. Apply operator + -> 11.

The Interview Questions They’ll Ask

  1. “What is an AST?”
  2. “How do Babel/ESLint work?”
  3. “Explain lexical scoping implementation.”

Hints in Layers

Hint 1: Use Acorn Use the acorn library to generate the AST so you can focus on the interpreter part.

Hint 2: The Evaluate Function Create a evaluate(node, env) function. Switch on node.type.

Hint 3: Binary Expressions If node.type === 'BinaryExpression', recursively evaluate left and right, then apply the operator.

Hint 4: Functions For functions, store the function definition (params + body) in the environment. When called, create a new env with parent = current env.

Books That Will Help

Topic Book Chapter
Interpreters “Structure and Interpretation of Computer Programs” Ch. 4 (Metalinguistic Abstraction)

Project 7: Virtual DOM Engine (Diffing Algorithm)

  • File: LEARN_JAVASCRIPT_DEEP_DIVE.md
  • Main Programming Language: JavaScript
  • Alternative Programming Languages: TypeScript
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 5. The “Industry Disruptor” (React/Vue)
  • Difficulty: Level 4: Expert
  • Knowledge Area: Browser API / Algorithms
  • Software or Tool: Vanilla JS
  • Main Book: “Learning React, 2nd Edition” (for concepts)

What you’ll build: A simplified React. You’ll write a createElement function (JSX factory), a render function, and a diff algorithm that compares two VDOM trees and applies the minimal set of changes to the real DOM.

Why it teaches Browser API: You realize that document.createElement is slow. You learn exactly what “reconciliation” means. You’ll see why keys are needed in lists and how batching updates improves performance.

Core challenges you’ll face:

  • Recursion: Walking two trees simultaneously to find differences.
  • Patching: creating a list of instructions (PATCH_TEXT, REPLACE_NODE, UPDATE_PROPS) and applying them.
  • Event Delegation: Attaching events efficiently.

Key Concepts:

  • DOM Tree: It’s just a data structure.
  • Diffing/Reconciliation: O(n) heuristic algorithms.
  • Reflow/Repaint: Why we minimize DOM touches.

Difficulty: Expert Time estimate: 2 weeks Prerequisites: Recursion, DOM API.


Real World Outcome

You will create a mini-framework where updates are batched and efficient.

Example Output:

const app = (count) =>
  h('div', { id: 'container' }, [
    h('h1', {}, 'Count is ' + count),
    h('button', { onclick: () => render(count + 1) }, 'Increment')
  ]);

// Initial render
render(0);
// Click button -> render(1)
// Console Log: [PATCH] TextNode changed from "0" to "1".

The Core Question You’re Answering

“Why is React faster than jQuery for complex updates?”

Concepts You Must Understand First

  1. DOM API
    • appendChild, replaceChild, setAttribute.
    • Book Reference: “JavaScript: The Definitive Guide” Ch. 15
  2. Tree Traversal
    • DFS (Depth First Search).

Questions to Guide Your Design

  1. Diffing Strategy
    • If a node changes type (div -> span), do I bother checking children? (No, replace the whole subtree).
  2. Props Diffing
    • How do I detect if a property changed? (Iterate keys).

Thinking Exercise

Trace Diff

Old: <div><span>A</span></div> New: <div><span>B</span></div>

  1. Root div matches.
  2. Child span matches.
  3. Child text A vs B. Differs.
  4. Create Patch: TEXT_UPDATE.

The Interview Questions They’ll Ask

  1. “How does the Virtual DOM work?”
  2. “What is Reconciliation?”
  3. “Why do we need keys in React lists?”

Hints in Layers

Hint 1: VNode Structure h(tag, props, children) just returns a JSON object { tag, props, children }.

Hint 2: Mount mount(vnode) creates the real DOM element recursively.

Hint 3: Diff diff(oldNode, newNode) returns a patch object (e.g., { type: 'TEXT_CHANGE', text: '...' }).

Books That Will Help

Topic Book Chapter
Algorithms “Grokking Algorithms” (Recursion & Trees)

Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor
1. Lodash Rebuild Intermediate Weekend ⭐⭐ ⭐⭐
2. Event Loop Sim Intermediate Weekend ⭐⭐⭐ ⭐⭐⭐
3. Custom Promise Advanced 1 Week ⭐⭐⭐⭐ ⭐⭐
4. Reactive System Advanced 2 Weeks ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
5. Retro Classes Intermediate Weekend ⭐⭐
6. JS Interpreter Master 1 Month+ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
7. Virtual DOM Expert 2 Weeks ⭐⭐⭐⭐ ⭐⭐⭐⭐

Recommendation

  1. Start with Project 2 (Event Loop Sim): It’s visual, distinct, and solves the biggest confusion in JS (async timing).
  2. Then do Project 3 (Promises): It follows naturally from the Event Loop.
  3. For mastery, tackle Project 6 (Interpreter): It is the ultimate test of understanding language mechanics.

Final Overall Project: The “Meta-Browser” Game Engine

What you’ll build: A 2D game engine that runs in the browser but uses your own runtime for game logic.

  1. Use your Event Loop (Proj 2) to manage the game tick.
  2. Use your Reactive System (Proj 4) for game state (score, health).
  3. Use your Virtual DOM (Proj 7) to render the UI (HUD, menus).
  4. Use your Class System (Proj 5) for Game Entities.

Why: It forces all these disparate concepts to coexist. The Event Loop drives the updates; Reactivity drives the UI; Classes structure the logic.

Summary

This learning path covers JavaScript internals through 7 hands-on projects.

# Project Name Main Language Difficulty Time Estimate
1 Lodash Rebuild JavaScript Intermediate Weekend
2 Event Loop Sim JavaScript Intermediate Weekend
3 Custom Promise JavaScript Advanced 1 Week
4 Reactive System JavaScript Advanced 2 Weeks
5 Retro Classes JavaScript Intermediate Weekend
6 JS Interpreter JavaScript Master 1 Month+
7 Virtual DOM JavaScript Expert 2 Weeks

Expected Outcomes

  • You will never be confused by this or asynchronous execution order again.
  • You will understand how frameworks like React and Vue work internally.
  • You will be able to debug complex memory and performance issues.
  • You will have built a mini-version of the JS ecosystem (Engine, Framework, Library).

```