JavaScript : Prototype

JavaScript : Prototype

Let's go deeper into an object.

Prerequisites

  • Datatypes

  • Object

Try running the below code. We defined a new person object with properties firstname and lastname, and run toString method on the object.

const person = {
   firstname:"Rohan",
   lastname:"Kamal"
}

console.log(person.toString());  // [object Object]

Did you notice the method toString returned successfully without any errors, but we never defined toString method in person object. So where it came from?

To understand it, first, we need to understand a few methods,

  • Object.getOwnProperties(obj)

  • Object.hasOwn(obj, propertyName)

The first method Object.getOwnPropertyNames(obj) returns all names of properties owned by the obj. Let's try for our person object.

const ownProperties = Object.getOwnPropertyNames(person);
console.log(ownProperties); // // [firstname, lastname]

The Second method Object.hasOwn(obj, propertyName) checks, whether given a propertyName property is owned by obj or not. Let's try for our person object for toString property.

console.log(Object.hasOwn(person, 'toString')) //false

From the above, we can confirm that toString does not belong to person. So, the question is still the same, where toString came from? Now let's see what else we have in person object. Run the below code,

console.log(person)

/* {
firstname : "Rohan"
lastname : "Kamal"
[[Prototype]] : { 
    constructor : ƒ Object() 
    hasOwnProperty : ƒ hasOwnProperty()
    isPrototypeOf : ƒ isPrototypeOf()
    propertyIsEnumerable : ƒ propertyIsEnumerable()
    toLocaleString : ƒ toLocaleString()
    toString : ƒ toString()
    valueOf : ƒ valueOf()
    __defineGetter__ : ƒ __defineGetter__()
    __defineSetter__ : ƒ __defineSetter__()
    __lookupGetter__ : ƒ __lookupGetter__()
    __lookupSetter__ : ƒ __lookupSetter__()
    __proto__ : null
    get __proto__ : ƒ __proto__()
    set __proto__ : ƒ __proto__()
}*/

If you observed, toString is present under [[Prototype]] property of the person object. It is an internal property in every object. We call it simply the prototype of an object. Now, the follow-up question arises of where this [[Prototype]] came from. It means javascript is doing something behind the scene, every time we create an object.

What is a prototype?

The [[prototype]] is an internal property of every object, initialized during object creation. It allows populating of common properties among objects created using the same constructor.

Let's understand it through person object. When we created person following steps were performed,

  1. Call new Object() constructor.

  2. Creates a new Object with fistname and lastname as properties.

  3. Assigns [[prototype]] of object as Object.prototype.

Yes!, Whenever an object is created with object literal syntax, JavaScript calls Object() constructor. It creates a new object and assigns [[prototype]] as Object.prototype. To verify it run the below code.

Object.getPrototypeOf(person) === Object.prototype; //true

Object.prototype is nothing, just a property of the in-built object Object, which gets assigned to [[prototype]] property of every newly instantiated object created from Object() constructor.

So, during the calling of toString method over the person object, JS firsts look for its own methods, if it failed to find any match then it goes into deeper into the object prototype [[prototype]]. To learn more about Object.prototype check this MDN Reference.

The most important point to note here is that the value of the [[prototype]] depends on the constructor used to create the object. In the above example, we were playing with plain objects created using Object() constructor so all objects were assigned Object.prototype as prototype.

Suppose we create an array using array literal syntax as below,

const arr = [1, 3, 4, 5, 6];

Arrays are created using Array() constructor in JavaScript, so every array object will have a prototype as Array.prototype. Let's verify it

Object.getPrototypeOf(arr) === Array.prototype; // true

Ways to assign prototypes?