Skip to Content
Course content

230: Common JavaScript Interview Questions on Prototypes

Click on the "Edit" button in the top corner of the screen to edit your slide content.

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:

  1. Fix the prototype chain so that Merchant inherits from NPC.
  2. Move the trade method from the constructor to the Merchant.prototype to ensure memory efficiency.
  3. Add a "shadowing" property to a specific merchant instance named silas that overrides the speak method 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."
Rating
0 0

There are no comments for now.

to be the first to leave a comment.