-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
229: Common JavaScript Interview Questions on Closures and this
If you've started interviewing for JS roles, you've probably noticed that interviewers are obsessed with closures and the this keyword. It's almost a rite of passage. They aren't just testing if you know the definitions; they're checking if you actually understand how the JavaScript engine handles memory and execution context.
"I get the definition of a closure, but why would I actually use one in a real project?"
In textbooks, closures are usually explained with a simple counter. In the real world, I use closures primarily for data privacy. Since JavaScript didn't have truly private class fields for a long time, closures were our only way to "hide" variables from the global scope so other parts of the app couldn't accidentally mess with them.
Check this out. Imagine you're building a module to handle an API token. You don't want the token sitting in a global variable where any script can grab it:
function createTokenManager(initialToken) {
let token = initialToken; // This variable is "private"
return {
updateToken: (newToken) => {
token = newToken;
console.log("Token updated!");
},
getToken: () => {
return `Bearer ${token}`;
}
};
}
const myManager = createTokenManager("abc-123");
console.log(myManager.getToken()); // "Bearer abc-123"
console.log(myManager.token); // undefined - it's hidden!
The inner functions updateToken and getToken form a closure. They "remember" the environment where they were created, giving them exclusive access to that token variable. It's a clean way to encapsulate state.
"Why does this suddenly stop working when I put my method inside a callback?"
This is the single most common point of frustration for developers. The rule of thumb is: this is not determined by where a function is defined, but by how it is called.
I've seen this a hundred times in event listeners or timers. Look at this snippet:
const user = {
name: "Alex",
greet: function() {
console.log(`Hi, I'm ${this.name}`);
}
};
// This works fine
user.greet(); // "Hi, I'm Alex"
// This fails
setTimeout(user.greet, 1000); // "Hi, I'm undefined" (or an error in strict mode)
Why? Because setTimeout doesn't call user.greet(); it takes the function itself and calls it later in a different context (usually the global window or undefined). The link to the user object is severed. To fix this, you can use .bind() to explicitly lock the context, or wrap it in an arrow function.
"What's the actual difference between an arrow function and a regular function when it comes to this?"
Regular functions create their own this context every time they are called. Arrow functions, however, don't have their own this at all. Instead, they inherit this from the surrounding code (lexical scoping).
This makes arrow functions a godsend for closures. If you're inside a class method and you need to run a forEach or a map, using an arrow function ensures that this still refers to your class instance, not the array being iterated over.
class Timer {
constructor() {
this.seconds = 0;
}
start() {
setInterval(() => {
this.seconds++; // 'this' correctly refers to the Timer instance
console.log(this.seconds);
}, 1000);
}
}
const myTimer = new Timer();
myTimer.start();
If I had used function() { this.seconds++; } inside that setInterval, it would have crashed because this would have pointed to the global Window object, which doesn't have a seconds property. I almost always prefer arrow functions for callbacks for exactly this reason.
📋 Practical Task
Build a Private Score Tracker with Context Binding
Your task is to create a createGame function that manages a player's score using a closure to keep the score private. However, you must also implement a "bonus" system that uses a separate method, requiring you to handle the this context correctly.
- Create a function
createGamethat initializes ascorevariable at 0. - Return an object with three methods:
addPoint(): Increments the score by 1.getScore(): Returns the current score as a string (e.g., "Current score is 5").applyBonus(multiplier): This method should be a regular function that usesthisto reference abonusValueproperty on the returned object, then adds that multiplied value to the privatescore.
- Initialize a game instance, set a
bonusValueproperty on that instance, and use asetTimeoutto callapplyBonusafter 1 second. Ensure you use.bind()or an arrow function so thatthis.bonusValueis accessed correctly within the timer.
There are no comments for now.