Understanding JavaScript Prototype in Simple Language

Understanding JavaScript Prototype in Simple Language

Hello World, prototype is a fundamental concept every developer delving into JavaScript must understand. In this post, I intend to explain the JavaScript's prototype to you in an easily digestible manner. If you are ready, let's get started.

What is Prototype

Every JavaScript object or function has a special hidden or internal property that is empty by default. This internal property can reference another object. At each time we create a function in JavaScript, JavaScript engine adds an extra property called prototype to the created function. This prototype property is an object (called as prototype object) The object the internal property points to is what we call a "prototype object". So Prototype property is simply a reference to another object. This is important as it helps have access to some methods stored in memory without recreating them from scratch. Consider the example code using the constructor

//Define the blueprint for manufacturing cars
function Car(){
this.model= "Audi";
this.year = 2021
this.seat = 5
this.drive = function(){
return "I am a cruising "
};

}
//create a new car object so we can inherit the properties of the Car
const car1 = new Car()
console.log(car1.design()); // I am a sleek vehicle
//This concept helps us extend the functionality of car1 by simply focusing on the new things to add to it

Meaning Of Prototype In English Language vrs JS

In English language, we may define a prototype as the first or preliminary version of a device from which other forms are developed.

Similarly, in the world of JavaScript, there is a prototype which is the first object or function from which other objects are developed.
In our example above, we developed car1 from Car object, making Car the prototype of car1

Why Is The Prototype Pattern Important ?

A prototype object serves as blueprint for each object the constructor creates. If the prototype of a constructor used contains a property make as in the example above, then each object created by that same constructor will also have this same property.

With this concept, anytime we read a property from an object and it is missing, JavaScript will automatically check the prototype object, see if the property is available there and take the value of the property from there. This pattern provides as an easy way to implement inheritance in JavaScript a concept that allows objects to inherit methods from the prototype.

Prototypal Inheritance

In javaScript, we can often use built-in methods such as

 .length, .map() and .join()

on our strings, arrays and object. Even though we never explicitly specify them, these methods are internal properties every object have. Any object you create, can inherit or have access to these in built methods. That explains why we can use the example below to get the length of an array

const num=[2, 4, 5, 21, 10, 13]
console.log(num.length) //  6

So how do we get the length of the array to be 6 ? Lets console.log(num) and see what is under the hood. When we console.log(num) we have access to the following

(6) [2, 4, 5, 21, 10, 13]
0: 2
1: 4
2: 5
3: 21
4: 10
5: 13
length: 6
__proto__: Array(0)

The proto above is that internal or hidden property that gives as access to all the in-built array methods in JavaScript. Any object we create, can inherit this "proto " property and have access to a method that was not explicitly created by the object.

Setting The Prototype Property

As mentioned earlier, the property [[Prototype]] is internal and hidden, but we can set it using the

_proto_  //not the recommended method of setting prototype though

Let's take a look at how to set a prototype property on an object

//parent object
let vehicle = {
     tyres : 4,
     make: "Audi"
}

// define a new object 
let sedan = {
    year: "2021"
}

sedan.__proto__ = vehicle 
// set vehicle to be the prototype of sedan 
// Now if we read a property from sedan and it is missing,
// JavaScript will automatically look at the prototype, in this case **vehicle ** and  and inherit  the property from there.
//Now if can have access to the "make" property
console.log(sedan.make)  // returns Audi
  • Scenario 2: Let's take another look on how to set a prototype on an object
let animal = {
    legs: 4,
    jumps: true, 
    walk(){
        return "Animal can walk "
    }
}

let sheep ={
    furs: true,
    feeds: "grass"
}
//set animal to be the prototype of sheep
sheep.__proto__ = animal
//Now all the properties and methods of animal becomes available in sheep.
// Such properties are called inherited
//If we have  any method in animal it can be accessed or inherited by the sheep object
//walk() is taken from the prototype
console.log(sheep.walk()) //  Animal can walk

Prototype Chain

When an object gets a request for a property that it does not have, the first reaction is to check the prototype to see if we can locate the property. If we still cannot find it, we search the prototype's prototype and so on this what we refer to as prototype chain. It is basically an object looking upward to find where it inherited a property from

Let see how that works

let animal = {
    legs: 4,
    jumps: true, 
    walk(){
        return "Can walk "
    }
}

let feed ={
    eats: "grass",
     __proto__: animal // set animal to be the prototype of feed

}
let horse = {
    hoof: true,  
    fur: true, 
      __proto__: feed  //set feed to be the prototype of horse
}
//horse accesses the walk() method
console.log(horse.walk()) // Can walk

With the above , if we try to access the walk() method from the horse object and it is not available, we look for it in the feed object(parent protoptype), if we still can't access the method, we look finally at and in the animal object (grand parent prototype) , we eventually find out that the "walk()" method was created in the animal object. That is why the horse object can have access to the walk() method.

Recommend Way Of Setting Prototype

If you have understood the concept of prototype, then the next bit about constructors should not be confusing, let's dig further. The recommended way of setting the prototype of an object is Object.create instead of the proto used earlier.

Object.create very simply returns a new object with the specified prototype and any additional properties you want to add. For our purposes you use it like so

//Define the blueprint for manufacturing cars
function Car(name, yearMade, passengers){
this.name = name
this.year = yearMade
this.manufacturer= "VW"
this.passengers = passengers

}
//Extend the functionality of the blueprint 

//set prototype of Car object to getDesign method
Car.prototype.getDesign = function(){
console.log(`I am a sleek ${this.name} vehicle`) 
}
//set prototype of Car object to getPessenger method
Car.prototype.getPessenger = function(){
console.log(`The ${this.name} can take up to ${this.passengers} passengers`)
}

//create a constructor function
function Sedan(name, passengers){
this.name =name
this.passengers = passengers

}
//set the prototype of the Sedan object to a new object that has a copy of Car.prototype and all its props
Sedan.prototype = Object.create(Car.prototype);
//Any new instance of the constructor function can inherit all properties of the Car object prototype
AudiSedan = new Sedan("Audi2021", 4)
//access the getDesign method 
AudiSedan.getDesign() // "I am a sleek Audi2021 vehicle"
AudiSedan.getPessenger() //"The Audi2021 can take up to 4 vehicle"

After creating the constructor for Sedan we set it’s prototype to a new object that has a copy of Car.prototype.. Now any new object created from the Sedan constructor can inherit all the methods of the Car prototype

In Conclusion

To summarize, prototype is basically a method that was set or initialized when a function was first created. When we create a function, the JavaScript engine creates a prototype object for that function and adds a prototype property to the function. Any instance of that function will have access to all the prototype object that was set by the function.
This then helps to extend the functionality of the object as new instances can inherit all the prototype objects that has been defined.

Trust you learnt something new ? Your feedback will be greatly appreciated, Me daa se .

PS: Me daa se means "Thank You" in Twi, one of the most popular dialects in my country Ghana