Problem with creating objects with constructor function syntax
Let’s create objects person1 and person2 using the Human constructor function
var person1 = new Human("Virat", "Kohli"); var person2 = new Human("Sachin", "Tendulkar");
i.e. every object created using the constructor function will have it’s own copy of properties and methods. It doesn’t make sense to have two instances of function fullName that do the same thing. Storing separate instances of function for each objects results into wastage of memory. We will see as we move forward how we can solve this issue.
As shown in the above image, Human constructor function has a prototype property which points to the prototype object. The prototype object has a constructor property which points back to the Human constructor function. Let’s see an example below:
To access prototype property of the Human constructor use the below syntax:
As seen from the above image prototype property of the function is an oject (prototype object) with two properties:
- constructor property which points to Human function itself
Creating an object using the constructor function
As shown in the above image, person1 object which is created using the Human constructor function has a dunder proto or __proto__ property which points to the prototype object of the constructor function.
//Create an object person1 using the Human constructor function var person1 = new Human("Virat", "Kohli");
As it can be seen from the above image, both person1’s dunder proto or __proto__ property and Human.prototype property are equal let’s check if they point at the some location using === operator
Human.prototype === person1.__proto__ //true
This shows that person1’s dunder proto property and Human.prototype are pointing to the same object.
Now, lets’s create an another object person2 using the Human constructor function
var person2 = new Human("Sachin", "Tendulkar"); console.log(person2);
Above console output shows that even person2’s dunder proto property is equal to the Human.prototype property and they points to the same object.
Human.prototype === person2.__proto__ //true
person1.__proto__ === person2.__proto__ //true
Above statement proves that the person1’s and person2’s dunder proto properties points to Human constructor function’s prototype object.
Prototype object of the constructor function is shared among all the objects created using the constructor function.
As prototype object is an object, we can attach properties and methods to the prototype object. Thus, enabling all the objects created using the constructor function to share those properties and methods.
New property can be added to the constructor function’s prototype property using either the dot notation or square bracket notation as shown below:
name and age properties have been added to the Human prototype
Let’s analyze what happened when we did console.log(person.name) Let’s check if person object has name property
As we can see that person1 object is empty and it does not have any property except it’s dunder proto property. So how does the output of console.log(person.name) was “Ashwin”?
Let’s create an another object person2 using the Person constructor function.
var person2 = new Person(); //Access the name property using the person2 object console.log(person2.name)// Output: Ashwin
Now, let’s define a property name on the person1 object
person1.name = "Anil" console.log(person1.name)//Output: Anil console.log(person2.name)//Output: Ashwin
In case of person2, name property is not present on the object. Hence, it outputs person2’s proptotype property name.
Problems with the prototype
As prototype object is shared among all the objects created using the constructor function, it’s properties and methods are also shared among all the objects. If an object A modifies property of the prototype having primitive value, other objects will not be effected by this as A will create a property on its objects as shown below.
Here (line 1 and 2), both person1 and person2 does not have name property, hence they access the prototypes name property and hence the output is same for both.
When person1 want to have different value for the name property, it creates a name property on its object.
Consider another example to display the issue with proptotypes when the prototype object contains a property of reference type
In the above example, person1 and person2 points to the same friends array of the prototype object. person1 modifies friends property by adding another string in the array.
Because the friends array exists on Person.prototype, not on person1, the changes made in the friends property by person1 objects are also reflected on person2.friends (which points to the same array).
If the intention is to have an array shared by all instances, then this outcome is okay. But here this was not the case.
To solve the problems with the prototype and the problems with the constructor, we can combine both the constructor and function.
- Problem with constructor: Every object has its own instance of the function
- Problem with the prototype: Modifying a property using one object reflects the other object also
To solve above both problmens, we can define all the object specific properties inside the constructor and all shared properties and methods insdie the prototype as shown below:
In the above example, friends property of person2 did not change on changing the friends property of person1.