Thursday, January 03, 2013

what's new - a look at the Javascript "new" operator

Happy new year!

Over the years, I have developed a love-hate relationship with Javascript. Every now and then, I would have some kind of epiphany and be completely in awe of the beauty of the language, only to be struck a few months later by the realisation that I lack understanding in some of the most fundamental concepts of the language. This, I believe, is because, coming from a traditional OO background, I just followed all those "classical inheritance" examples, and never really questioned what is actually going on underneath in this inherently classless language.

Some time ago, I was trying to understand Object.create() more, especially how it differs from calling new Foo(). I got depressed pretty quickly as I was struck again by one of those "I thought I knew it all" moments.

I am not going to actually discuss the difference between Object.create() and new Foo() here. There are plenty of informative articles on the web which explain this topic very well. Instead I am going to just focus on the semantic of the new operator.

Jumping from one blog post to another, I came across this very short and simple article: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Inheritance_Revisited. Here, it states that when you call

 var o = new Foo();  

Javascript actually does this (note the "or something like that" disclaimer):

 var o = new Object();  
 o.[[Prototype]] = Foo.prototype;  
 o.Foo();  

I particularly like this snippet because, while new Foo() is such a widely used language construct, these three lines contain some of the most crucial Javascript concepts which often get overlooked or misconceived by many "classical hierarchists".

  • Foo, the constructor function, is simply a standard function in Javascript. Every function in Javascript has a property called prototype.
  • This prototype property is completely different from the [[Prototype]] prototype that all Javascript objects have.
  • An object's [[Prototype]] prototype points to the object that the current object inherits its states (properties) from.
  • The (constructor) function's prototype property points to the object that the newly constructed object will inherit its states (properties) from. This establishes the newly constructed object's prototype chain. Javascript looks up an object's property by following the prototype chain until a property with the matching name is found.
  • Therefore, changes to the prototype object's state will be reflected in the inheriting object even after object creation. On the other hand, when a property is being set on an object, the property will be created on the object itself.
  • By default, the prototype object itself has a constructor property, which is why the constructor function can be invoked on the newly created object itself. Incidentally, this means we can be sure that "this" in a constructor function always refer to the newly created object. If you are not familiar with how the late binding of "this" works in Javascript, just google for it.

Next time you extend a "class" in Javascript by specifying Car.prototype = new Vehicle(); (or Car.prototype = Object.create(Vehicle.prototype); which is actually slightly different), think about what is happening underneath, how the prototype chain is being established, and what it actually looks like, etc.

Finally, I must give a shout out to Angus Croll for his excellent article: http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/. If I had not come across this, I would probably still be none the wiser!