Every constructor function has a property called prototype. You can add properties and methods to it. Using a constructor function, When you create a new object, the object has access to prototype methods.
Sample code:
let Car = function(color) {
this.color = color;
};
Car.prototype.getColor = function() {
return this.color;
};
let redCar = new Car('red');
console.dir(redCar);
If you inspect the redCar object, you will see the following.In the above image, the
getColor()
is not a part of the redCar object. There is another property called __proto__
, which is set automatically. You can think of __proto__
as the creator of redCar. If you expand __proto__
, the getColor method and the constructor are displayed. Constructor is the a reference to the Car Constructor that created redCar.
If you expand the Car constructor, the prototype property of the constructor is displayed. If you further expand the prototype property, the getColor method is displayed.
The getColor method from __proto__ is actually a reference to the one you added to the constructor’s prototype. It looks tricky, however, all you care about is that __proto__, the creator of redCar, has the getColor method. Hence, when you call the
redCar.getColor()
method, JavaScript will look inside the redCar object. If the method doesn’t exist in the object, it will look for the method in the object’s creator, which is __proto__
. It will find it and execute it.
So, let’s analyze a little more and discover how is
__proto__
created. If you further expand __proto__
, you will see its creator, which is the master __proto__
. This is basically a master object called Object
(the letter ‘O’ is capitalized). Every object in JavaScript is created from Object
. It also has some methods. One of the methods is toString()
. When you call this method on redCar, JavaScript will first search for this method in the redCar object. If it can’t find it there, it keeps searching for the method all the way to the end of the prototype chain.
There are pros and cons of using prototype inheritance. The best part is, the inheritance makes objects lighter. The drawback is that every time you call a method that is not a part of the object, it looks for the method up the prototype chain. Hence, it makes it a little slower. The workaround is, if you are going to call this method frequently, store it in a variable to avoid the lookup.
let toString = Object.toString;
console.log(redCar.toString());
Overwriting Object Methods
If you want to customize the toString() method, you can add it to the object’s prototype. However, there are times when you want to make method available to every object. In such case, add it to the master object’s prototype. This would shadow the native toString() method.
Object.prototype.toString = function(){
return `color:${this.color}`;
};
let Car = function(color) {
this.color = color;
};
Car.prototype.getColor = function() {
return color;
};
let redCar = new Car('red');
console.dir(redCar.toString());
In next article, I will show you how to use Object.create()
method to set prototype of one object to another. Follow the link below. Object.create() method
2 thoughts on “JavaScript Prototype Explained”