20
DecA Complete Guide to Prototypes in JavaScript: How They Work and Why They Matter
Prototype in JavaScript
Prototypes in JavaScript might sound a bit technical at first, but they’re simpler than you think. Have you ever wondered how objects in JavaScript can share methods or properties without copying them everywhere? That is where prototypes come in, and they make it all happen behind the scenes.
In this JavaScript tutorial, we will explore what prototypes are, how they work, and why they are a game-changer for your JavaScript code. By the end, you will feel confident using prototypes to build smarter, reusable, and more efficient applications.
Read More: Defining Namespace or Nested Objects in JavaScript |
Importance of prototypes in object creation and inheritance
Have you ever needed to create multiple objects that share the same behavior? Instead of repeating the same code, you can use prototypes to make your work easier. They let you define properties and methods once and reuse them across all your objects.
With prototypes, you do not have to worry about writing duplicate code. It allows you to share methods between objects efficiently, saving memory and making your code cleaner. Doesn’t that sound like a smarter way to handle inheritance in JavaScript? Understanding prototypes helps you build faster, scalable, and more maintainable applications.
Read More: Understanding Inheritance and Different Types of Inheritance |
JavaScript Prototype Illustration
When you work with JavaScript, understanding prototypes is essential. It's like discovering how objects share properties and methods without copying them. Prototypes let you create a chain of relationships between objects, making your code more efficient and easier to manage.
1. Visual and Code-Based Demonstration of Prototype Relationships
Prototypes work behind the scenes to connect objects. It's like a hidden chain where objects can "borrow" properties or methods from another object. Let’s explore this with a simple example:
// A base object with a method
const vehicle = {
start: function() {
return "Vehicle started";
}
};
// A car object linked to the vehicle prototype
const car = Object.create(vehicle);
car.wheels = 4;
// Using the inherited method and own property
console.log(car.start()); // "Vehicle started"
console.log(car.wheels); // 4
Output:
Vehicle started
4
Explanation:
- vehicle: This is a base object that contains a method
start
. - car: This object is created using
Object.create(vehicle)
, so it inherits fromvehicle
. - Inheritance: The
car
object can use thestart
method defined invehicle
. - Own property: The
car
object has its own property,wheels
, which is set to4
. - Output: The program prints "Vehicle started" from the inherited method and
4
from its own property.
Real-World Examples Showing Prototype Linkage
Example: Library System
// Prototype for all books
const book = {
borrowed: false,
borrow: function() {
this.borrowed = true;
return `${this.title} has been borrowed.`;
}
};
// Specific book linked to the book prototype
const specificBook = Object.create(book);
specificBook.title = "JavaScript Basics";
console.log(specificBook.borrow()); // "JavaScript Basics has been borrowed."
console.log(specificBook.borrowed); // true
Output:
JavaScript Basics has been borrowed.
true
Explanation:
- book: This is a prototype object representing the base behavior of books. It has a property
borrowed
and a methodborrow
that changes theborrowed
status totrue
. - specificBook: This is an object created using
Object.create(book)
. It inherits theborrow
method from thebook
prototype. - title property: The
specificBook
object gets its owntitle
property, set to "JavaScript Basics." - Inheritance in action: When calling
specificBook.borrow()
, it updates the inheritedborrowed
property totrue
and returns a message using thetitle
. - Output: The program prints the borrowing message and confirms that the book is now marked as borrowed.
Defining Methods in the JavaScript Prototype Object
In JavaScript, you can define methods directly on an object's prototype, allowing all instances of that object to share the same method. This saves memory and makes your code more efficient. It’s like giving a group of objects a common set of tools, so they don’t each need their own individual copy of the tools.
Adding Methods to an Object's Prototype for Reuse
When you add a method to a prototype, it is available to all instances of that object. This means that instead of duplicating the method for each object, you can reuse it across many objects. Let's look at how to do this:
Example: Defining Shared Methods in Prototypes
// Constructor function to create a new object
function Person(name, age) {
this.name = name;
this.age = age;
}
// Define a shared method on the prototype
Person.prototype.greet = function() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
};
// Creating instances of Person
const person1 = new Person("Alice", 30);
const person2 = new Person("Bob", 25);
// Using the shared method
console.log(person1.greet()); // "Hello, my name is Alice and I am 30 years old."
console.log(person2.greet()); // "Hello, my name is Bob and I am 25 years old."
Output:
Hello, my name is Alice and I am 30 years old.
Hello, my name is Bob and I am 25 years old.
Explanation:
- In this example, we define the
greet
method on the prototype of thePerson
constructor function. - Both
person1
andperson2
are instances of thePerson
constructor, and they both share the samegreet
method, which is stored on the prototype. - By sharing the method, memory is optimized because there is only one copy of the
greet
method, regardless of how many objects are created.
Practice with these Articles: |
Defining Methods with Constructor Functions in JavaScript
- In JavaScript, a constructor function is used to create objects with similar properties and methods.
- You define methods inside the constructor function to give each instance of an object its behavior.
- The constructor function itself is used with the new keyword to create new objects.
Adding methods to a constructor function's prototype for reuse
- When you add methods to the prototype of a constructor function, all instances of that constructor share the same method.
- This is more memory efficient, especially when many instances are created.
Example: Creating Person objects and adding a greet method
// Define a constructor function for creating 'Person' objects
function Person(name, age) {
this.name = name;
this.age = age;
}
// Add a method to the 'Person' prototype
Person.prototype.greet = function() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
};
// Create new instances of Person
const person1 = new Person("Alice", 25);
const person2 = new Person("Bob", 30);
// Both instances can use the greet method defined in the prototype
console.log(person1.greet()); // "Hello, my name is Alice and I am 25 years old."
console.log(person2.greet()); // "Hello, my name is Bob and I am 30 years old."
Output:
Hello, my name is Alice and I am 25 years old.
Hello, my name is Bob and I am 30 years old.
Explanation:
- Person constructor: The constructor function
Person
is used to create new objects withname
andage
properties. - Prototype method: The
greet
method is added to the prototype ofPerson
, so all instances ofPerson
will inherit this method. - Creating instances: Two instances,
person1
andperson2
, are created using thenew
keyword and thePerson
constructor. - Method invocation: The
greet
method is invoked in both instances, which returns a personalized greeting using thename
andage
of each person. - Output: The output shows the greeting for each person as defined in the
greet
method.
Defining Methods in an Individual Object
In JavaScript, you can add methods directly to an individual object rather than adding them to the object's prototype. This means that only that specific object will have the method, making it unique to that object. Unlike prototype methods, which are shared among all instances of an object, methods added directly to an object cannot be reused by others unless explicitly added.
Adding methods directly to a single object
This approach is useful when you need a method that is only relevant to a specific instance of an object. It’s like giving that particular object a custom feature.
Example: Adding methods directly to an individual object
// Create an individual object
const person = {
name: "Alice",
age: 25
};
// Add a method directly to this object
person.greet = function() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
};
console.log(person.greet()); // "Hello, my name is Alice and I am 25 years old."
Explanation:
- person object: The object is created with properties
name
andage
. - greet method: The method
greet
is added directly to theperson
object. This method returns a greeting message using the object's properties. - Output: The method is called on the
person
object and logs the personalized greeting.
Comparison Between Individual Object Methods and Prototype Methods
JavaScript offers two ways to add methods to objects: through prototypes or directly on individual objects. The choice depends on whether the method should be shared across all instances or be unique to a specific object. Here, we compare the two approaches to understand their benefits and drawbacks.
Prototype Methods vs. Individual Object Methods
Prototype Methods: These are shared by all instances of the object, meaning they use less memory. Any change to the method affects all instances of the object.
Individual Object Methods: These methods are only available to that specific object, and can’t be shared with other instances unless added explicitly.
Getting Prototype Linkage
Understanding how JavaScript objects are linked to their prototypes is crucial for inheritance. When accessing properties or methods, JavaScript will check the object's prototype chain to find them. Knowing how to retrieve and inspect this prototype linkage can help you understand how inheritance works.
Understanding Prototype Chains
Prototype chains allow objects to inherit properties and methods from their prototypes. When JavaScript looks for a property or method, it first checks the object itself. If it doesn’t find the property, it will look at the prototype, and so on, up the prototype chain.
Example using Object.getPrototypeOf
const person = {
name: "Alice"
};
const prototype = Object.getPrototypeOf(person);
console.log(prototype); // Will show Object.prototype
Example using __proto__
const person = {
name: "Alice"
};
console.log(person.__proto__); // Will show Object.prototype
Shadowing
In JavaScript, an object can shadow or override a property or method inherited from its prototype. This happens when an object defines a property or method with the same name as one in its prototype, causing the object’s property to take precedence.
Property and Method Shadowing in Prototypes
Shadowing occurs when an object defines a property or method with the same name as one in its prototype. The property or method in the object will be used instead of the one in the prototype.
Example: Overriding Prototype Properties or Methods
const person = {
name: "Alice",
greet: function() {
return "Hello from prototype!";
}
};
// Overriding the greet method
person.greet = function() {
return "Hello from Alice!";
};
console.log(person.greet()); // "Hello from Alice!" (Shadows the prototype method)
Prototype Inheritance
Prototype inheritance is a powerful feature in JavaScript that allows objects to inherit properties and methods from other objects. This is the basis for object-oriented programming in JavaScript.
Read More: Object-Oriented Programming Concepts |
Using Prototypes for Property and Method Inheritance
Objects can inherit from other objects by linking to their prototype. When an object inherits from a prototype, it can access all the properties and methods defined on that prototype, even if those properties are not directly part of the object.
Example: Inheriting from a Prototype
const animal = {
sound: "Roar",
makeSound: function() {
return this.sound;
}
};
// Create a new object that inherits from animal
const lion = Object.create(animal);
lion.name = "Lion";
console.log(lion.name); // "Lion"
console.log(lion.makeSound()); // "Roar" (inherited from animal)
JavaScript Prototype Chaining
JavaScript's prototype chaining mechanism allows objects to inherit properties and methods not just from their own properties but also from their prototype’s properties. This chain continues until it reaches Object.prototype
.
Explanation of Prototype Chain Resolution
When JavaScript looks for a property or method, it starts with the object itself. If it doesn't find it, it searches the prototype and then the prototype's prototype, continuing up the chain. The search ends when it reaches Object.prototype
.
Example: Prototype Chain Traversal
const person = {
name: "Alice"
};
const employee = Object.create(person);
employee.position = "Developer";
console.log(employee.name); // "Alice" (inherited from person)
console.log(employee.position); // "Developer" (own property)
Functional Instantiation and Prototypal Patterns
Functional instantiation is a common pattern in JavaScript that allows objects to be created via functions. By using constructor functions or the Object.create()
method, you can manage object creation and inheritance. These patterns are fundamental to understanding object-oriented principles in JavaScript.
Functional Instantiation
Functional instantiation refers to creating objects using functions. In JavaScript, this is often done by defining a function that acts as a constructor. When you call the function using the new
keyword, it creates a new object with the properties and methods defined in the constructor.
Creating Objects Through Functions
In this approach, you define a function and use it to generate new objects. When you use the new
keyword, it automatically sets up the this
context for the function, allowing you to assign properties and methods to the new object.
Example: Using a Constructor Function
// Constructor function to create a new object
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
};
}
// Creating a new object using the constructor function
const person1 = new Person("Alice", 30);
console.log(person1.greet()); // "Hello, my name is Alice and I am 30 years old."
Output:
Hello, my name is Alice and I am 30 years old.
Explanation:
- The constructor function
Person
is used to create new objects with propertiesname
andage
, as well as a methodgreet
. - When the object
person1
is created using thenew
keyword, the constructor initializes the object's properties. - The
greet
method outputs a message that includes the object'sname
andage
.
Functional Instantiation with Shared Methods
To improve memory usage, you can share methods across all instances of an object by defining them outside the constructor function. This avoids creating duplicate methods for every instance and helps optimize memory usage.
Sharing Methods Across Instances to Save Memory
By placing methods outside the constructor, you ensure that all instances of the object share the same method, which reduces memory overhead. This technique is commonly used with the Prototype Design Pattern
Read More: Different Types of Design Patterns |
Example: Defining Shared Methods Outside the Constructor
// Constructor function with shared method outside
function Person(name, age) {
this.name = name;
this.age = age;
}
// Shared method defined on the prototype
Person.prototype.greet = function() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
};
const person2 = new Person("Bob", 25);
console.log(person2.greet()); // "Hello, my name is Bob and I am 25 years old."
Output:
Hello, my name is Bob and I am 25 years old.
Explanation:
- The
greet
method is shared across all instances ofPerson
because it is defined on the prototype, which helps reduce memory usage. - Even though each
Person
instance has its own properties, they all share the samegreet
method.
Object.create
Object.create()
is a method that allows you to create an object with a specified prototype. This method provides a simpler way to establish prototype chains and inherit properties from other objects.
Using Object.create to Set Up Prototype Chains
Object.create()
is used to create a new object with an explicit prototype, which can then be extended or modified as needed. This method is often used for inheritance when you want to set the prototype of a new object directly.
Explanation and Practical Examples
Using Object.create()
, you can easily set up inheritance and prototype chains. This method provides a more flexible and explicit way to link objects and define inheritance than constructor functions alone.
Example: Using Object.create
// Creating an object with Object.create
const animal = {
sound: "Roar",
makeSound: function() {
return this.sound;
}
};
// Create a new object that inherits from animal
const lion = Object.create(animal);
lion.name = "Lion";
console.log(lion.name); // "Lion"
console.log(lion.makeSound()); // "Roar"
Output:
Lion
Roar
Explanation:
- The
lion
object is created usingObject.create(animal)
, which sets the prototype oflion
to beanimal
. - The
lion
object inherits themakeSound
method fromanimal
and can access its own properties, likename
.
Functional Instantiation with Shared Methods and Object.create
This hybrid approach combines the benefits of functional instantiation, where you can define shared methods outside the constructor, with the flexibility of Object.create()
to set up prototype chains.
Combining the Benefits of Shared Methods and Object.create
By using Object.create()
to set up inheritance and defining methods on the prototype, you can create efficient objects that share common methods but still allow for individual properties and customization.
Code Examples Illustrating This Hybrid Approach
// Constructor function with shared method on the prototype
function Person(name, age) {
this.name = name;
this.age = age;
}
// Shared method defined on the prototype
Person.prototype.greet = function() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
};
// Creating an object with Object.create
const person3 = Object.create(Person.prototype);
person3.name = "Charlie";
person3.age = 28;
console.log(person3.greet()); // "Hello, my name is Charlie and I am 28 years old."
Output:
Hello, my name is Charlie and I am 28 years old.
Explanation:
- The object
person3
is created usingObject.create(Person.prototype)
, setting its prototype toPerson
. - The object shares the
greet
method defined on thePerson
prototype, while having its own propertiesname
andage
.
Prototypal Instantiation
Prototypal instantiation allows you to create objects directly from other objects, without using constructor functions. This is the most direct way of setting up inheritance in JavaScript.
Directly Creating Objects from Other Objects
With prototypal instantiation, you create a new object by using another object as its prototype. This method avoids the need for constructors and allows direct object inheritance.
Example: Leveraging Object Literals and Inheritance with Prototypes
// Create an object directly from another object
const animal = {
sound: "Roar",
makeSound: function() {
return this.sound;
}
};
// Directly creating an object that inherits from animal
const lion2 = Object.create(animal);
lion2.name = "Lion";
console.log(lion2.name); // "Lion"
console.log(lion2.makeSound()); // "Roar"
Output:
Lion
Roar
Explanation:
- The object
lion2
is created directly from theanimal
object usingObject.create()
. lion2
inherits themakeSound
method from theanimal
prototype and also has its own properties likename
.
Summary
This article covered how to define methods inside constructor functions and add them to the prototype for reuse in JavaScript. Constructor functions create objects with specific properties, and defining methods in the prototype allows all instances of that constructor to share the same method, saving memory. Using the prototype is an efficient way to add common behavior to multiple objects.Want to learn more about JavaScript? Sign up for the ScholarHat JavaScript Programming Course today and become a JavaScript pro! Don't miss your chance to improve your skills and take your career to the next level!
FAQs
function Person(name) { this.name = name; } Person.prototype.greet = function() { return `Hello, ${this.name}`; }; const person1 = new Person('John'); console.log(person1.greet()); // Accessing the prototype metho
Take our Javascript skill challenge to evaluate yourself!
In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.