Prototypes in Javascript

Understanding Prototypes in Javascript

Featured, Javascript

Hey, Today in this post we are going to discuss what are prototypes in javascript, and how they work.

Before moving on lets first discuss why prototypes are required in javascript.

Why Prototype ?

Lets take a example of a function

function createSuperHero(firstName, lastName){
    this.firstName = firstName;
    this.lastName = lastName;
    this.fullName = () => {
    	return `New Super Hero created ${this.firstName} ${this.lastName}`;
    }
}

const hero1 = new createSuperHero("Cat","Women");
const hero2 = new createSuperHero("Bat","Man");

console.log(hero1.fullName());
console.log(hero2.fullName());
console.log(hero1.fullName === hero2.fullName) // returns false;

In the above example we have created a function createSuperHero and then created two instances of that function. On executing the above code javascript will create two different reference of the function in memory each for hero1 and hero2
This is totally wastage of memory and to solve this problem we use prototypes in javascript.

Lets move ahead and see what is prototype

What is Prototype ?

When we create function javascript add a prototype property to that function. This prototype is a object having constructor property by default pointing back to the function on which this prototype object has been created

You can access prototype property by using createSuperHero.prototype


Lets see a example for prototype.

Reference: https://medium.com/better-programming/prototypes-in-javascript-5bba2990e04b
function createSuperHero(firstName, lastName){
    this.firstName = firstName;
    this.lastName = lastName;
}

createSuperHero.prototype.fullName = function() {
     console.log(`New Super Hero created ${this.firstName} ${this.lastName}`);
}

console.log(hero1.fullName());
console.log(hero2.fullName());
console.log(hero1.fullName === hero2.fullName) // returns true;

If you noticed in above example when we compare fullName method on hero1 and hero2 and it returned false beacuse both instances created separate reference to createSuperHero function in memory.
But when we assigned fullName as prototype of createSuperHero then both instances points to the same prototype object.

Reference: https://medium.com/better-programming/prototypes-in-javascript-5bba2990e04b

We can add more property to the prototype of main function and its get available to all created instances.

createSuperHero.prototype.age = 28;
createSuperHero.prototype.fullName = () =>{
     console.log(`New Super Hero created ${this.firstName} ${this.lastName} with age ${this.age}`);
}

If you do console.log(hero1), you will check there is a object called __proto__ pointing to its created function createSuperHero

What is __proto__ ?

__proto__ is an object inside every instance created on a function or class pointed towards to prototype of its function or class. In simple language we can say that __proto__ is the property of instance created an prototype is property of the function on which instance is created.

console.log(createSuperHero.prototype === hero1.__proto__) // return true
console.log(createSuperHero.prototype === hero2.__proto__) // return true
console.log(hero1.__proto__ === hero2.__proto__)

Lets dig deeper in magical world of prototype and learn more features prototype provides.

function createSuperHero(firstName,lastName){
    this.firstName = firstName;
    this.lastName = lastName;
    this.fullName = () =>{
        console.log(`New Super Hero created ${this.firstName} ${this.lastName}`);
    }
}


let superPower = {
    canFly : true,
    __proto__: new createSuperHero("Bat", "Man")
}

superPower.fullName()
console.log(superPower.canFly)

In the above example we have created createSuperHero function and assigned its instance to superPower Objects __proto__ object.
Now when we call superPower.fullName() it try to read its property in superPower object if not found then it checks in its prototype property (look from bottom to up). This is called prototypal inheritance.

Limitations:

There are only 2 limitations when using prototypes.

1) The refrence cant go in circles . Javascript will throw error if we try to assign __proto__ in circle.
2) The value of __proto__ can be either an object or null. Other types are ignored.

Writing with Prototypes

Prototype property is only used for reading. Write/Delete operation works differently with prototypes.

function createSuperHero(firstName, lastName){
    this.firstName = firstName;
    this.lastName = lastName;
    this.friends = ["a","b","c"]
    this.fullName = () => {
        return `New Super Hero created ${this.firstName} ${this.lastName}`;
    }
}

const hero1 = new createSuperHero("Cat","Women");
const hero2 = new createSuperHero("Bat","Man");

hero1.friends.push("d");
console.log(hero1.friends);
console.log(hero2.friends);

In this case hero1 will find friends in its __proto__ and change it . It will not affect the createSuperHero this.friends array.

for…in loop

The for…in loop iterates over inherited properties

let superHero = {
  walks: true
};

let batman = {
  fly: true,
  __proto__: superHero
};

/ Object.keys only returns own keys
console.log(Object.keys(batman)); // fly

// for..in loops over both own and inherited keys
for(let prop in batman) console.log(prop); // fly, then walks

I hope you enjoyed this post. In coming posts we will discuss more about javascript features.
Stay Tuned …

References:

https://javascript.info/prototype-inheritance

Other Posts you can check

Leave a Reply