Introduction
Welcome to Day 2! Today, we’re diving into one of the most fundamental and frequently asked topics in JavaScript interviews: JavaScript prototyping. Understanding the prototype model is crucial for demonstrating your proficiency in the language’s core mechanics. While modern ES6 classes provide a more familiar syntax for inheritance, they are built on top of the old-school prototype system. A strong grasp of the underlying mechanism is a hallmark of a seasoned developer.
What is JavaScript Prototyping?
In JavaScript, every object has an internal property, referred to as [[Prototype]], which points to another object. This “prototype object” is a blueprint from which other objects inherit properties and methods. This system, known as the JavaScript prototype chain, is how the language implements inheritance. When you try to access a property or method on an object, and it’s not found, JavaScript automatically traverses up the prototype chain to see if it exists on a prototype object. This process continues until it finds the property or reaches null.
JavaScript prototyping allows you to add new properties and methods to existing objects. When a method is added to a constructor’s prototype, it is shared among all instances created by that constructor, saving memory and promoting code reusability. Instead of creating a new function for every single object instance, they all point to the same function in the prototype.
Here is a simple, step-by-step guide to defining and using prototypes:
- Create a Constructor Function: Define a constructor function to act as a blueprint for your objects.JavaScript
function Person(name, age) { this.name = name; this.age = age; } - Add Methods to the Prototype: Add methods to the constructor’s prototype object. These methods will be inherited by all instances.JavaScript
Person.prototype.greet = function() { return "Hello, my name is " + this.name + " and I'm " + this.age + " years old."; } - Create Instances: Use the
newkeyword to create instances of the object.JavaScriptvar person1 = new Person("Ana", 30); var person2 = new Person("Soni", 25); - Access Prototype Methods: Call the shared method on any instance of the object.JavaScript
console.log(person1.greet()); // Output: Hello, my name is Ana and I'm 30 years old.
Common Interview Questions on Prototyping
Q1: Explain the difference between setting a property directly on an object vs. on its prototype.
Answer: A property set directly on an object is an “own property” that exists only for that specific instance. In contrast, a property set on an object’s prototype is shared among all instances of that object type. When a property is accessed, JavaScript first looks for it on the object itself. If it’s not there, it then looks up the JavaScript prototype chain. This process is known as property “shadowing,” where an own property “hides” a property of the same name on the prototype.
JavaScript
function Person(name) {
this.name = name;
}
var person1 = new Person("Alice");
var person2 = new Person("Bob");
// Set a property directly on person1
person1.age = 30;
console.log(person1.age); // Output: 30
console.log(person2.age); // Output: undefined
// Now, set a property on the prototype
Person.prototype.age = 25;
console.log(person1.age); // Output: 30 (own property takes precedence)
console.log(person2.age); // Output: 25 (inherits from prototype)
Q2: How do you check if an object inherits a specific property from its prototype?
Answer: You can use the hasOwnProperty() method, which is a key part of JavaScript prototyping. It returns true if a property is a direct property of an object and false if it is inherited from the JavaScript prototype chain. This is often a safer check than using the in operator, which returns true for both own and inherited properties.
JavaScript
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() { /* ... */ };
var person1 = new Person("Alice");
console.log(person1.hasOwnProperty('name')); // Output: true (defined directly on person1)
console.log('name' in person1); // Output: true
console.log(person1.hasOwnProperty('greet')); // Output: false (inherited from prototype)
console.log('greet' in person1); // Output: true
Q3: How do you create a constructor function with prototypes in JavaScript?
Answer: You can define a constructor function using the function keyword and then add properties and methods to its prototype object. This is the standard way to create objects and share behavior in pre-ES6 JavaScript, and it remains a core concept to understand for JavaScript interview questions.
JavaScript
function MyClass() {
// Constructor logic goes here
}
MyClass.prototype.myMethod = function() {
// Method implementation
};
Q4: Create a Person constructor function with name and age properties. Add a method greet() to its prototype that returns a greeting with the person’s name and age.
Answer: This can be accomplished by defining a Person function with this.name and this.age properties, and then assigning a new function to Person.prototype.greet.
JavaScript
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
return "Hello, my name is " + this.name + " and I'm " + this.age + " years old.";
};
var person1 = new Person("Soni", 30);
console.log(person1.greet());
// Output: Hello, my name is Soni and I'm 30 years old.
Q5: Implement a simple inheritance pattern using prototypes. Create a Vehicle constructor with a type property. Create a Car constructor that inherits from Vehicle and adds a color property.
Answer: You can implement JavaScript inheritance by calling the parent constructor using Vehicle.call(this, type) and then linking the prototypes using Object.create(Vehicle.prototype). It’s also important to correctly set the constructor property.
JavaScript
// Parent Constructor
function Vehicle(type) {
this.type = type;
}
Vehicle.prototype.start = function() {
return "The " + this.type + " is starting.";
};
// Child Constructor
function Car(type, color) {
Vehicle.call(this, type); // Call parent constructor for inheritance
this.color = color;
}
// Inherit from Vehicle's prototype
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car; // Correctly set the constructor reference
var car1 = new Car("SUV", "blue");
console.log(car1.type); // Output: SUV
console.log(car1.color); // Output: blue
console.log(car1.start()); // Output: The SUV is starting.
Q6: What happens if you modify a property on an object’s prototype?
Answer: Modifying a property on a prototype affects all objects that inherit from that prototype. This change will be visible on all instances, even those created before the modification was made. This is a powerful, yet potentially dangerous, aspect of JavaScript prototyping.
JavaScript
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return "Hello, " + this.name;
};
var person1 = new Person("Soni");
// Modify the prototype method
Person.prototype.greet = function() {
return "Hey there, I'm " + this.name;
};
// The change is reflected in the existing instance
console.log(person1.greet()); // Output: Hey there, I'm Soni
Q7: Explain the difference between a prototype and a property in JavaScript.
Answer: This is a fundamental distinction. A prototype is an object from which other objects inherit properties and methods. It forms the JavaScript prototype chain, which is the mechanism for inheritance. A property is a key-value pair associated with an object. Properties can either be “own properties” (defined directly on the object) or “inherited properties” (accessed via the prototype chain).
The key difference is that a prototype is an object itself, while a property is a characteristic or data point of an object. Prototypes are for sharing behavior, while properties define the state of an individual object.
Modern class Syntax and Prototyping
While the examples above show the traditional way of using prototypes, modern JavaScript (ES6 and beyond) provides the class and extends keywords as syntactic sugar over the same underlying prototype mechanism. Knowing both is a key differentiator in a technical interview.
JavaScript
class Vehicle {
constructor(type) {
this.type = type;
}
start() {
return "The " + this.type + " is starting.";
}
}
class Car extends Vehicle {
constructor(type, color) {
super(type);
this.color = color;
}
}
let newCar = new Car("Sedan", "black");
console.log(newCar.start()); // Output: The Sedan is starting.
Summary
Understanding the JavaScript prototype chain is a cornerstone of being a proficient JavaScript developer. By mastering these concepts, you can confidently answer advanced interview questions and write more efficient and maintainable code. Your journey to interview readiness continues tomorrow!
This article is part of our 100 Days of JavaScript Interview Prep series.