-
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)
230: Common JavaScript Interview Questions on Prototypes
I've sat in on dozens of technical interviews, and there is one specific moment where I can almost see the candidate's confidence vanish: the moment the interviewer asks them to explain the difference between prototype and __proto__. Most learners assume they are two names for the same thing—the "prototype of the object."
Let's look at why that's wrong. If you think they are the same, you'll write code like this and wonder why it's returning undefined:
function Robot(name) {
this.name = name;
}
const wallE = new Robot('Wall-E');
// The misconception: trying to add a method to the instance's "prototype" property
wallE.prototype.sayHello = function() {
console.log(`Beep boop, I am ${this.name}`);
};
wallE.sayHello(); // TypeError: wallE.sayHello is not a function
The reason this fails is that wallE (the instance) does not have a prototype property. Only the constructor function Robot has one. When you tried to set wallE.prototype.sayHello, you simply created a random new property on the wallE object called "prototype" and attached a function to it. You didn't touch the actual prototype chain at all.
The .prototype property is a blueprint, not the instance's link
Here is the mental model I use: think of Robot.prototype as a "package of shared traits" that the Robot function hands out to every single object it creates. The constructor doesn't use its own prototype property; it uses it as a template for others.
The actual link that exists on the instance is __proto__ (or more formally, accessed via Object.getPrototypeOf()). When you call a method on wallE, JavaScript doesn't look at Robot.prototype directly; it looks at wallE.__proto__. It just so happens that wallE.__proto__ points exactly to Robot.prototype.
function Robot(name) {
this.name = name;
}
// We add the method to the blueprint
Robot.prototype.sayHello = function() {
console.log(`Beep boop, I am ${this.name}`);
};
const wallE = new Robot('Wall-E');
const eve = new Robot('Eve');
console.log(wallE.__proto__ === Robot.prototype); // true
console.log(eve.__proto__ === Robot.prototype); // true
Prototypes are linked, not cloned
Another common interview trap is the "inheritance via copying" myth. Some developers think that when you create an instance, JavaScript copies all the methods from the prototype onto the new object. If that were true, memory usage would skyrocket as you created thousands of objects.
In reality, it's a live link. If I add a method to Robot.prototype after I've already created wallE, wallE instantly gains access to that method. I've seen candidates stumble here because they assume the object's capabilities are frozen at the moment of instantiation.
const wallE = new Robot('Wall-E');
// Adding a method AFTER the object was created
Robot.prototype.dance = function() {
console.log(`${this.name} is doing the robot!`);
};
wallE.dance(); // This works! The link is live.
Handling the "Shadowing" question
Finally, you'll likely be asked about "property shadowing." This happens when an instance has a property with the same name as one on its prototype. JavaScript always checks the object itself first. If it finds the property there, it stops looking and never even reaches the prototype.
I like to call this "the ego of the instance." The instance always gets the first word. If wallE has its own sayHello method, it will ignore the one on Robot.prototype entirely. This is a powerful way to override default behaviors for specific objects without breaking the shared blueprint for everyone else.
📋 Practical Task
Implementing a Shared Ability System for Game NPCs
You are building a simple RPG. You have a base NPC constructor and a Merchant constructor that should inherit from NPC. However, the current implementation is broken: the Merchant objects cannot access the speak method, and the trade method is being added inefficiently to every single instance instead of the prototype.
Your Task:
- Fix the prototype chain so that
Merchantinherits fromNPC. - Move the
trademethod from the constructor to theMerchant.prototypeto ensure memory efficiency. - Add a "shadowing" property to a specific merchant instance named
silasthat overrides thespeakmethod to return "..." instead of the default greeting.
function NPC(name) {
this.name = name;
}
NPC.prototype.speak = function() {
return `Hello, I am ${this.name}.`;
};
function Merchant(name, stock) {
NPC.call(this, name);
this.stock = stock;
// TODO: Move this method to the prototype!
this.trade = function() {
return `I have ${this.stock} items for sale.`;
};
}
// TODO: Fix the inheritance link here
// Merchant.prototype = ...
const silas = new Merchant('Silas', 5);
const elara = new Merchant('Elara', 12);
// TODO: Implement shadowing for silas.speak here
console.log(elara.speak()); // Should be: "Hello, I am Elara."
console.log(silas.speak()); // Should be: "..."
console.log(elara.trade()); // Should be: "I have 12 items for sale."
There are no comments for now.