There is a great article written by Douglas Crockford. I recommend everybody to read this article. By using Prototypal inheritance technique, we can create the instance of an object. Suppose, we have one object User, we want to create the instance of the user object and use it in different-2 places. In order to create the instance of an object, we can set the prototype property of an Constructor Function equal to the object and then we can instantiate that constructor function to create the instance of that object. Below is the create method that will help us to do so. This method is taken from Doug’s article.
//creating a method that will pops up //the new objects inherited with the old object. if ( Object.create !== "function" ) { Object.create = function (oldObj) { function F ( ) {} ; F.prototype = oldObj; return new F ( ); } }
Now let’s say we have one object User that has one property say name that is an array. It has getter setter methods to set and get the name value.
//User is a simple object contains 3 methods and one property User = { name : [], addName:function(n) { this.name.push(n); }, getName : function ( ) { alert(this.name); } }
Now, by using create method, we can create instances of the User object.
//creating one instance of User var obj1 = Object.create(User); obj1.addName("Rupesh"); obj1.getName( ); //creating another instance of the User var obj2 = Object.create(User); obj2.addName("Ritesh"); obj2.getName( );
We saw that how easily we can create the instances of an object and can use its properties and methods using Prototypal inheritance.
I like Prototypal inheritance because it has many advantages one of them is it saves memory. Because, when we create new object by putting old object in its prototype property then we don’t refer to the concrete old object rather we refer to the property of an object which has a link or which refer to or which points to the concrete old object. It also help us to create the loosely coupled architecture.
However, in above User object there is one problem!!
The problem is when you call obj1.getName( ) it will alert Rupesh. When you call obj2.getName( ) it will alert Rupesh, Ritesh. This is a problem!! This was never expected. We thought that we are creating two different new objects obj1 and obj2. Which will have their own name properties and will store different values. But it is not the case!!!
Let’s analyze the process !
When we write the code obj1.addName(“Rupesh”); The obj1, new object will look for the name property in obj1 object. It will not find the name property in the obj1 object. So, it will go to the prototype object which is a User object and there it will search for the name property and finally it updates the name property of the prototype object which is nothing but the User Object. Therefore, the next time when obj2.addName(“Ritesh”) is called, it again looks for name property in this (obj2) and it again fails to find the name property in obj2 object. Therefore, it searches in obj2’s prototype object for name property. There exists User object that has name property and obj1 has already entered “Rupesh” in this property so obj2 again enters “Ritesh” in the same name property and hence when we do obj2.getName( ) then it says “Rupesh,Ritesh”.
Whatever data is entered by the obj1 in name property. It is inserted in the prototype objects name property that is also shared with obj2. That means, they are sharing the same name property. It’s like a static property that is being used by the multiple instances of the User object. But, that was not intended. We wanted a new fresh object in each instance.
In order to achieve that, we can introduce one method to User object say init. In this method we will initialized the name property with a new array and assign it to the instance object “this”.
User = { init:function ( ) { // we are initializing its name property in new instance or new object. this.name = []; }, name :[], addName:function(n) { this.name.push(n); }, getName : function ( ) { return this.name; } }
Now if we write below code to set and get the name property then each instance will have different or their own values.
//creating one instance of User var obj1 = Object.create(User); //calling its init method obj1.init( ); //here we are adding the same name property //to the new instance of the User object. obj1.addName("Rupesh"); obj1.getName( ); //creating another instance of the User var obj2 = Object.create(User); obj2.init( ); obj2.addName("Ritesh"); obj2.getName( );
Now the obj1.getName ( ) will return Rupesh and obj2.getName will return Ritesh. Because, now obj1 and obj2 will have common shared methods but they will have their own distinct name properties. I think, I was able to explain the prototypal inheritance clearly. If you have any suggestions then plz put your comments, I want to learn more from you.
Related Articles
- Javascript Jems – a new take on objects (i-programmer.info)
- Class – digg – Class creation and management for jQuery – Project Hosting on Google Code (code.google.com)
- CLiki : ParenscriptClassicOO (cliki.net)
- (really) understanding javascript prototypes (javascriptweblog.wordpress.com)
- Javascript Jems – Object factories, constructors and clones (i-programmer.info)
- Determining if an object property exists (nczonline.net)
- Book Review: Object-Oriented JavaScript (elegantcode.com)
- Classes in JScript – Part III: Class Hierarchy and Data Encapsulation (blogs.msdn.com)
- Advantages of prototype based OO over class based – Stack Overflow (stackoverflow.com)
This is good. Hope to see more such things from you.
Thanks Satish ji.
I learned many things from you. I will try to summarize them up and will write soon.
[…] your plugin’s methods in the prototype of jquery object. $.fn is the alias for the prototype of the jquery object. In our above example, […]