Stop watching tutorials. Start writing code that breaks, reading errors that teach, and building things that work — because you understand why.
No credit card. No pressure. Just JavaScript.
Why does `this` change depending on where I call it?
The question that's broken more hearts than any other in JavaScript.
`this` is about call-site, not write-site.
`this` isn't where your function lives — it's who calls it. In a method, `this` is the object. In a plain function call, it's `undefined` (or `window` in old code). Arrow functions inherit `this` from their parent scope and never get their own. Once you internalize "who's calling this right now?" — the confusion evaporates.
// Regular function — this = who calls it const user = { name: "Maya", greet() { // ✅ this = user object console.log(this.name); }, greetLater() { setTimeout(() => { // ✅ arrow fn: this = user console.log(this.name), 1000); } }; user.greet(); // "Maya"
A closure is a function that remembers its birthplace.
When a function is created, it carries a reference to the scope it was born in — even after that scope is gone. This is how counters, private variables, and module patterns work. It's not magic. It's just that functions in JavaScript are first-class citizens that travel with their luggage.
function makeCounter() { let count = 0; // private! return function() { count++; return count; }; } const clicks = makeCounter(); clicks(); // 1 clicks(); // 2 // count is unreachable outside — // that's the closure protecting it.
Do I actually need to understand closures?
Yes. And once you do, you'll see them everywhere — including in code you've already written.
Why does my code run before the data arrives?
JavaScript doesn't wait. Here's how to make it wait politely.
JavaScript is single-threaded. Async is how it multitasks.
When you fetch data, JavaScript doesn't pause — it moves on and comes back when the data is ready. Promises represent that "coming back." `async/await` is just cleaner syntax for the same idea. The mental model: you're describing a sequence of things to do when they're ready, not blocking the whole thread to wait.
// ❌ This runs before data arrives const data = fetch("/api/user"); console.log(data); // Promise {pending} // ✅ async/await: readable, correct async function getUser() { const res = await fetch("/api/user"); const user = await res.json(); console.log(user.name); // "Priya" ✅
Classes are syntax sugar. Prototypes are the actual mechanism.
JavaScript doesn't have "real" classes like Java or Python. When you write `class Dog extends Animal`, the engine builds a prototype chain under the hood. You don't need to write prototype code daily — but knowing it exists means you'll never be surprised when `instanceof` behaves unexpectedly, or when a library's object mysteriously has methods you didn't define.
// What classes actually compile to: function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + " speaks"); }; // class syntax does the same thing class Dog extends Animal {} // ← prototype chain
Do I actually need to understand prototypes, or can I just use classes?
Classes are prototypes in a tuxedo. You should meet both.
What you'll actually build
Every module is a project. Every project is something you'd put on GitHub. No filler, no theory-only lessons.
Variables & Scope
Functions & Closures
The `this` Keyword
Async JavaScript
// Module 01 — no account required
From stuck to shipping
“I'd been stuck in tutorial hell for 8 months. Console was the first thing that made closures actually click — not just 'what' they are, but why they exist.”

Tariq Osei
Junior Frontend Dev · Stripe
“I quit my retail job with three months of savings and bet on Console. Got a developer role in 14 weeks. The project-based approach is the real deal.”

Priya Nair
Software Engineer · Shopify
“Other courses taught me to copy code. Console taught me to read error messages. That one skill difference is enormous.”
Marcus Webb
Frontend Developer · Linear