Understanding the JavaScript Prototype Chain and Inheritance
In this blog post, we'll dive deep into the world of JavaScript and explore the concepts of Prototype Chain and Inheritance. These two concepts are fundamental to understanding how objects work in JavaScript, and they play a critical role in making JavaScript a versatile and powerful language. So, whether you're a beginner or an experienced JavaScript developer, it's essential to understand these concepts to build more efficient and scalable applications. Let's begin!
The JavaScript Object
Before we dive into the prototype chain and inheritance, it's important to understand the basics of JavaScript objects. An object in JavaScript is a collection of key-value pairs, where each key is a string or a symbol, and the value can be any data type, including other objects. Objects are created using the object literal syntax or the new
keyword with a constructor function. Here's an example:
const person = { firstName: "John", lastName: "Doe" };
In the example above, we've created a simple person
object with two properties: firstName
and lastName
.
The Prototype Chain
In JavaScript, every object has a prototype, which is another object that it inherits properties and methods from. This prototype object has its own prototype, creating a chain of objects known as the prototype chain. This chain ends with the null
object, which has no prototype.
The prototype chain plays a vital role in how JavaScript resolves property and method lookups. When you try to access a property or method on an object, JavaScript first looks for it on the object itself. If it doesn't find it there, it moves up the prototype chain, checking each object in the chain until it either finds the property/method or reaches the end of the chain (i.e., the null
object).
To understand the prototype chain better, let's consider an example:
const person = { firstName: "John", lastName: "Doe" }; console.log(person.toString()); // Output: "[object Object]"
In the example above, we're trying to access the toString()
method on the person
object. However, we didn't define the toString()
method on the person
object. So, JavaScript looks up the prototype chain and finds the toString()
method on the Object.prototype
object, which is the prototype of our person
object.
You can access an object's prototype using the Object.getPrototypeOf()
method or the deprecated __proto__
property. Here's an example:
const personPrototype = Object.getPrototypeOf(person); console.log(personPrototype); // Output: {constructor: ƒ Object(), ...} console.log(person.__proto__); // Output: {constructor: ƒ Object(), ...}
The new Keyword and Constructor Functions
Constructor functions are special functions in JavaScript that are used to create new objects. They follow the naming convention of starting with a capital letter. When a constructor function is called with the new
keyword, JavaScript creates a new object, sets its prototype to the constructor function's prototype
property, and calls the constructor function with the new object as its context (this
).
Let's create a Person
constructor function and use it to create a new person
object:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } const person = new Person("John", "Doe"); console.log(person); // Output: Person {firstName: "John", lastName: "Doe"}
In the example above, the Person
constructor function sets the firstName
and lastName
properties on the newly created person
object. The new object's prototype is setto the Person.prototype
object. This means that any properties or methods defined on the Person.prototype
object will be available to all objects created using the Person
constructor function.
Let's add a method to the Person.prototype
object:
Person.prototype.getFullName = function() { return this.firstName + " " + this.lastName; }; console.log(person.getFullName()); // Output: "John Doe"
In the example above, we added the getFullName()
method to the Person.prototype
object. Since the person
object's prototype is set to the Person.prototype
object, it has access to the getFullName()
method.
Inheritance in JavaScript
Inheritance is a way of creating new objects that inherit the properties and methods of existing objects. JavaScript uses prototype-based inheritance, which means that inheritance is achieved through the prototype chain.
To create an object that inherits from another object, you need to set the new object's prototype to the existing object's prototype. The most common way to do this is by using the Object.create()
method.
Let's create a Student
object that inherits from the Person
object:
function Student(firstName, lastName, studentID) { Person.call(this, firstName, lastName); this.studentID = studentID; } Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; const student = new Student("Jane", "Doe", "S12345"); console.log(student.getFullName()); // Output: "Jane Doe"
In the example above, we created a Student
constructor function that inherits from the Person
constructor function. We first call the Person
constructor function using the call()
method to set the firstName
and lastName
properties. Then, we set the Student.prototype
object to a new object created with the Person.prototype
object as its prototype. Finally, we set the constructor
property of the Student.prototype
object back to the Student
constructor function.
Now, when we create a new student
object, it has access to the getFullName()
method from the Person.prototype
object because it's in its prototype chain.
The class Syntax
Although JavaScript is a prototype-based language, ES6 introduced the class
syntax to make it easier to create constructor functions and set up inheritance. The class
syntax is just syntactic sugar over the existing prototype-based inheritance system.
Let's rewrite our Person
and Student
objects using the class
syntax:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return this.firstName + " " + this.lastName; } } class Student extends Person { constructor(firstName, lastName, studentID) { super(firstName, lastName); this.studentID = studentID; } } const student = new Student("Jane", "Doe", "S12345"); console.log(student.getFullName()); // Output: "Jane Doe"
In the example above, we used the class
syntax to create the Person
and Student
objects. The extends
keyword sets up the prototype chain, so the Student
object inherits from the Person
object. The super()
function is used to call the parent class's constructor function.
Conclusion
In this blog post, we've explored the JavaScript prototype chain and inheritance in-depth. We covered the basics of JavaScript objects, the prototype chain, constructor functions, prototype-based inheritance, and the ES6 class
syntax.
Understanding the prototype chain and inheritance is crucial for writing efficient and scalable JavaScript code, as it allows you to create objects that share common properties and methods, making your code more modular and easier to maintain. Moreover, it enables you to take advantage of the powerful concept of polymorphism, where objects of different types can be treated as objects of a common type.
Here are a few key takeaways from this post:
- Every JavaScript object has a prototype, which is another object it inherits properties and methods from.
- The prototype chain is a series of objects linked through their prototypes, ending with the
null
object. - Constructor functions are used to create new objects and set their prototypes.
- Inheritance in JavaScript is achieved through the prototype chain, by setting the prototype of one object to another object's prototype.
- ES6 introduced the
class
syntax, which is a more convenient way of working with constructor functions and setting up inheritance, but it's still built upon the prototype-based inheritance system.
With this understanding of the JavaScript prototype chain and inheritance, you can now create more efficient, modular, and scalable applications. Keep learning and experimenting with different object-oriented programming patterns in JavaScript to further enhance your skills and expertise as a JavaScript developer.
Sharing is caring
Did you like what Mehul Mohan wrote? Thank them for their work by sharing it on social media.
No comments so far
Curious about this topic? Continue your journey with these coding courses: