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
- Foundation: “You Don’t Know JS: Scope & Closures” (Understand variable lifecycle).
- Mechanics: “You Don’t Know JS: Objects & Classes” (Understand the object model).
- 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
myBindrequires handling whatthisrefers to when the function finally runs. - Callback Signature: Ensuring your
mappasses(item, index, array)correctly. - Timing Control:
debounceandthrottlerequire mastering closures andsetTimeoutstate.
Key Concepts:
- Higher-Order Functions: Functions that take functions as args or return them.
thisKeyword: How it changes based on invocation.- Closures:
debouncerelies 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
mapandbindactually 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:
- 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
- The
thisKeyword- What determines the value of
this? - How does
.apply()changethis? - 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
- What determines the value of
- 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:
- 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)
- Implementing
bindbindreturns 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)
- Implementing
debounce- Where do you store the
timeoutId? - What should happen if the function is called again before the timeout clears?
- Where do you store the
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
fnusesthis?
The Interview Questions They’ll Ask
Prepare to answer these:
- “Implement
Array.prototype.mappolyfill.” - “What is the difference between
call,apply, andbind?” - “Implement a debounce function.”
- “Why is
thisundefined in my callback?” - “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
processAPI - 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:
- 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
- Task Queues
- What is the difference between the Task Queue (Macrotasks) and the Microtask Queue?
- Which queue does
process.nextTickgo 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:
- 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?
- The “Tick”
- How do you simulate the engine checking the stack? (A
whileloop that runs as long as there are queues).
- How do you simulate the engine checking the stack? (A
- 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:
- “What is the output of this async code snippet?” (Very common)
- “Explain the difference between Macrotasks and Microtasks.”
- “Does
setTimeout(fn, 0)run immediately?” - “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:
- If stack not empty, run stack item.
- Else if microQueue not empty, move ONE item to stack.
- 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:
- Three states:
PENDING,FULFILLED,REJECTED. .then()chaining (returning a new MyPromise).- Asynchronous execution of handlers (even if resolved immediately).
- 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(orsetTimeout) 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
.thento 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:
- Inversion of Control
- Why are callbacks “trust issues”?
- Book Reference: “You Don’t Know JS: Async & Performance” Ch. 2
- Microtasks
- Why must
.thencallbacks run asynchronously even if the promise is already resolved? - Book Reference: “You Don’t Know JS: Async & Performance” Ch. 3
- Why must
Questions to Guide Your Design
- State Management
- How do you ensure state can only transition once? (
if (state !== PENDING) return)
- How do you ensure state can only transition once? (
- Callback Storage
- If
then()is called on a PENDING promise, where do you put the callback?
- If
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
- “What happens if you resolve a Promise with itself?”
- “Implement
Promise.allandPromise.race.” - “Why is
catchjust syntax sugar forthen?”
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.
- See
Count: 0. - Open console, type
state.count++. - The DOM updates to
Count: 1instantly.
The Core Question You’re Answering
“How do modern frameworks (Vue, Solid, MobX) know when to re-render?”
Concepts You Must Understand First
- Proxy
- How to intercept
getandset? - Book Reference: “Deep JavaScript” (online) - Proxies
- How to intercept
- Dependency Graph
- What is a Subscriber/Publisher pattern?
Questions to Guide Your Design
- Automatic Registration
- How do we know who is asking for
state.count? (The globalactiveEffecttrick).
- How do we know who is asking for
- Memory Management
- Why use
WeakMapfor the dependency storage?
- Why use
Thinking Exercise
Trace:
effect(() => console.log(state.a + state.b))
effectstarts. Setsactive.state.agetter triggers. Addsactivetoa’s subscribers.state.bgetter triggers. Addsactivetob’s subscribers.effectends. Clearsactive.
The Interview Questions They’ll Ask
- “What is a Proxy in JavaScript?”
- “Explain the difference between
Object.defineProperty(Vue 2) andProxy(Vue 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.prototypedelegates toParent.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__vsprototype: The classic interview stumbling block.newOperator: 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:
- Constructor Functions
- What happens when a function is called with
new? - Book Reference: “You Don’t Know JS: Objects & Classes” Ch. 4
- What happens when a function is called with
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
- Linking Prototypes
- How do you ensure
Dog.prototypeinherits fromAnimal.prototypebut doesn’t share the same object?
- How do you ensure
- The Constructor Property
- How do you repair the
.constructorproperty after linking prototypes?
- How do you repair the
Thinking Exercise
Trace new Dog()
newcreates empty object.- Links
__proto__toDog.prototype. - Calls
Dog.init. Dog.initcallsthis._super(Animal.init).- Properties set on
this.
The Interview Questions They’ll Ask
- “Explain prototypal inheritance.”
- “What does
newdo? (Step by step)” - “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
outervariables are accessible butinnerones are not. - AST Traversal: Writing a recursive
evaluate(node)function. - Variable Declaration: Handling
constvslet(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
- ASTs
- Use
astexplorer.netto see what code looks like as a tree. - Book Reference: “Structure and Interpretation of Computer Programs” Ch. 4
- Use
- Visitors Pattern
- Separating the algorithm from the object structure.
Questions to Guide Your Design
- Function Calls
- How do I represent a “Function Call”? (Creating a new environment with arguments bound to parameters).
- Return Statements
- How do I handle
returndeep inside a recursive evaluation? (Throwing a special Return value? Returning a wrapped object?).
- How do I handle
Thinking Exercise
Trace Evaluation
Code: x + 1 with Env {x: 10}.
evaluate(BinaryExpression)evaluate(Identifier x)-> Lookup Env -> 10.evaluate(Literal 1)-> 1.- Apply operator
+-> 11.
The Interview Questions They’ll Ask
- “What is an AST?”
- “How do Babel/ESLint work?”
- “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
- DOM API
appendChild,replaceChild,setAttribute.- Book Reference: “JavaScript: The Definitive Guide” Ch. 15
- Tree Traversal
- DFS (Depth First Search).
Questions to Guide Your Design
- Diffing Strategy
- If a node changes type (
div->span), do I bother checking children? (No, replace the whole subtree).
- If a node changes type (
- 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>
- Root
divmatches. - Child
spanmatches. - Child text
AvsB. Differs. - Create Patch:
TEXT_UPDATE.
The Interview Questions They’ll Ask
- “How does the Virtual DOM work?”
- “What is Reconciliation?”
- “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
- Start with Project 2 (Event Loop Sim): It’s visual, distinct, and solves the biggest confusion in JS (async timing).
- Then do Project 3 (Promises): It follows naturally from the Event Loop.
- 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.
- Use your Event Loop (Proj 2) to manage the game tick.
- Use your Reactive System (Proj 4) for game state (score, health).
- Use your Virtual DOM (Proj 7) to render the UI (HUD, menus).
- 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
thisor 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).
```