Sunday, March 17, 2013

Difference Between Protoype and __proto__ in Javascript


So what’s the difference between __proto__ and prototype property in Javascript?


The prototype is used to create __proto__  Simple!

Yes, I know. That statement does not help much in terms of explaining what is going on :) But stick with me, the plan is to make it clear by the end of the post.

So let's dig into explaining this stuff!

The subject of prototype is related to Javascript objects and object creation and relation; so before going further, I recommend first reading Understanding Constructor Function and this Keyword in Javascript as this would provide some basic information that would help in understanding some of the basic concepts needed.


Let Us First Look At Prototype Property.


In Understanding Constructor Function and this Keyword in Javascript, I explained that Javascript functions are indeed Objects; albeit a little different from your regular objects since they have certain behaviours that are unique: for example, you can call a function but you can't call an object. Because of this, just like you would do to any object, you can add properties and methods to a Javascript function!

So what has this got to do with prototype?

Well, prototype is a property of Javascript function. Albeit a native one, meaning that you do not have to add it, every Javascript function you have, automatically gets it.

Let us confirm this:

var fooFunction =  function() {
//
}

now check if prototype is indeed a property of fooFunction

console.log(fooFunction.prototype); // does not print undefined so its there
console.log(typeof fooFunction.prototype) // prints "object"

But for an object that is not a function, let us see if it also has the prototype property:
var regularObj = {
      id : 1,
      type : 'regularObject'
}
now if you try to access prototype property of regularObj you get undefined. i.e:

console.log(regularObj.prototype) // prints undefined

which confirms that prototype property is only available by default to Functions.

So now that we have established that prototype are properties only found in Function objects, the next question is: "What does it contain and what is it used for"? But before we go into that, we need to first take a look at another concept: prototype chain in Javascript.


Prototype chain

I like to think of the prototype chain as a chain of <strike>command</strike> request. Its a chain that links you to where to go in other to get your requests answered. And if you do not get an answer, it leads or points you to the next place where you can make the request again. Think of a typical support call centre. A call comes in and a question is asked. if the call centre operative knows the answer, it is given. If not, most likely, the call would be directed to another department who would be better suited to provide the answer. This process of forwarding the request in other to get it answered may very well go on until an answer is provided or all possible source for an answer has been exhausted and at that point, the caller is told that his/her question/request can not be answered. 

Something similar happens when you have an object and you call a property on it in Javascript. for instance:

var justAnObj = {
prop1 : "I am property one",
prop2: function () {
  console.log("I am property two");
},
prop3:true
}


calling justAnObj.prop1 or any of the above defined properties can be said to be making a request for that property from the object. But when you request for a property that is not defined: i.e. justAnObj.prop4, you get undefined. But before the undefined is returned, there is actually a lookup that happens which is very similar to the support centre scenario we just described above. And you only get the undefined returned when this chain of look up has been exhausted and prop4 cant be found anywhere! 

But wait! where is this look up chain I am talking about. I can't see it defined anywhere!

Every object in Javascript has an internal pointer which points to the look up chain; another object. This object is also referred to as the prototype. But since this could be easily confused with the prototype property of a function, I would prefer to refer to it as Internal prototype So if a property is not found in an object, it is searched for in the object that its Internal prototype refers to. And, you know the cool thing? Since the Internal prototype always refers to an object, and every object has this internal pointer (Internal prototype property) that links to an object (the prototype), it means the look up for the requested property would continue recursively until the property is found and returned or until we reach the end of the look up chain which is Object objectthe only Object that does not have an Internal Prototype. It is at this point that undefined is returned.

Let us confirm that all these is not bullocks or black magic.

Still using the justAnObj defined above, do the following

console.dir(justAnObj.constructor.prototype) 
or better still 
console.dir(Object.getPrototypeOf(justAnObj)

Confirm that it prints out an object. Do not bother about the nature of what is shown in the console or how it got there for now. It would all fit together soon!

So let us now bring this knowledge to the prototype property of Functions. And see how it helps us understand the difference between prototype and __proto__

From the post Understanding Constructor Function and this Keyword in Javascript we know that we can use Functions to create objects. And we also know that Functions have a prototype property.  And from above we now know that every Javascript object has an internal prototype property which points to its prototype object, which is used in the prototype chain.

Yes we know all these but  how does these all tie together?

Like this:
When an object is created with a Constructor function in Javascript, its internal prototype property would be set to the prototype property of the Function that was used to create it.

Lets see this in action.

Make a constructor function.
var ConFunc = function () {
this.desc = "I am a constructor function"
}
Now add stuff to the prototype property of ConFunc function:

ConFunc.prototype.language = "javascript";
ConFunc.prototype.browser = "chrome";
Now create an Object from it
var myObj = new ConFunc();

Now call the properties defined:
myObj.desc // prints I am a constructor function"
myObj.language // prints Javascript"
myObj.browser // prints chrome"
You see what is going on? even though .language and .browser property were not defined in the Constructor function, you still have access to them from the object created. This is because, as explained, a look up was done and led to the function's prototype, which had the property we wanted.

For a final confirmation that everything is as I say, try and access the internal prototype of the myObj object:

Object.getPrototypeOf(justAnObj)

This would print out the following
Object {language: 'javascript', browser: 'chrome'}

which is the prototype property of the ConFunc that we defined.

So now we see that every object has an internal prototype, and that this points to the prototype property of the function that was used in creating them. The proceeding question to that would maybe be, "what about the objects that are created using object literals, where do their internal prototype property points to"?

It points to the global Javascript Object object.

Well, remember that above we printed out the internal prototype for justAnObj? the result we got was the Object object. Simple as that. The prototype of literal objects point to Object object.


Now finally, how __proto__ fits into the picture?

The __proto__

You see that I have been referring to an objects prototype as internal prototype property and I have used justAnObj.constructor.prototype and Object.getPrototypeOf(justAnObj) to get access to it. I could have done the same using __proto__ which is a pseudo property of any object that can be used to get access to its prototype. 

The only thing is that __proto__, according to specification is meant to be hidden and inaccessible to the developers. Even though, most browsers flaunt this rule,  ideally it should not be used.

This restriction may change with the upcoming ECMAScript 6 standard, but for now I would still prefer Object.getPrototypeOf

So I guess at this point, having read the preceding, the statement I made initially, at the beginning of this post: The prototype is used to create __proto__ should now makes sense.

1 comment:

Franz Zemen said...

Thanks for this and your previous posts. Great refresher.