Picking up Javascript - Being classy Feb 08 2009

My current work at CakeDC allows me to be on IRC a lot – like all day. And while I’m often quite silent during the day, I do scan through a few PHP related channels and I’ve noticed a trend of PHP developers who just don’t get Javascript. Either they don’t have the experience, or they do have experience and think its icky. However, their clients want ‘ajax’ so they begrudgingly use this terrible language that doesn’t even have classes. Well recently I’ve been writing a pile of Javascript, in fact there have been quite a few days where I am spending more time in Javascript than PHP. So I wanted to talk about some of the things I’ve learned about the worlds most popular language.

No class.

While Javascript has class on its list of reserved words it doesn’t actually have an implementation of that keyword. This is a big obstacle for many developers coming from classical inheritance background. This combined with first order functions and javascript starts looking really strange to the PHP developer. One of the reasons that Javascript doesn’t currently have classes is that it is a prototype based language and it was originally modeled after Scheme and has more in common with functional languages like Lisp and Haskell than C family languages. This family of languages often doesn’t have classes as they are based on functions, and javascript is no different. The designers of Javascript intended the language to be used something like:

var Person = function ( name ) { this . name = name ; } Person. prototype . sayHi = function ( ) { alert ( this . name ) ; }

This however is a little bit wierd and cumbersome looking for most people familiar with C family languages. But fear not, although Javascript has no classes doesn’t mean that it lacks a way to create the same type of code reuse that classes afford. The two primary approaches are by using prototypes and closures. Both offer ways to create objects that behave like traditional classes. Personally, I’m a fan of prototypal inheritance, and its also the approach that libraries like MooTools and PrototypeJS take.

Prototypes

Every object in Javascript has a prototype, this prototype describes what features (properties and methods) are going to be available on all instances of a given object type. Using prototypes as we saw above can be cumbersome but it has number of advantages over closures in my opinion.

First, adding features into an object’s prototype adds those features to all instances previously created, and those yet to be created. Now, let that sink in for a second. This is a huge and very important point. By using prototypes you have the ability to change objects on the fly, and add methods into existing objects, even the native objects. Furthermore, these changes will be updated automatically on all instances. In classical patterns, if you want to add a method to an object, you need to create a subclass and inject the subclass into the correct place. In Javascript you just modify the prototype.

String . prototype . trim = function ( ) { return this . replace ( /^\s*/ , '' ) . replace ( /\s*$/ , '' ) ; }

Now the base String object doesn’t have a trim() method by default, however we can just add one in. All String objects will have a trim() method after the above code executes. This is just a simple example of how much power prototypal inheritance affords.

So how does that work?

Prototypes in Javascript are checked each time a specific instance doesn’t have a particular method/property. So if you call myVar.foo() where myVar is an instance of Person . First, the interpreter checks the instance for a foo() method. If it doesn’t find it there it will recursively scan through all the prototypes for a foo() method. If at the end of this, foo() is still not found an error will be raised. Another interesting features of prototypes is that methods contained in an object’s prototype, are not bound to a specific instance and consume less memory than functions contained within closures.

So how does this make inheritance?

Well we’ve seen how prototypes allow you to augment an object type with new methods and properties. This augmentation is the basis of inheritance in Javascript. By leveraging prototypes you can take features from one objects prototype and add them to another, or tack on new features as needed. Both MooTools and PrototypeJS use this in their Class objects. I have a simple version that I use when working with no library.

var Class = function ( features ) { var klass = function ( noStart ) { if ( typeof this . init == 'function' && noStart != 'noInit' ) { return this . init . apply ( this , arguments ) ; } return this ; } ; for ( var key in this ) { klass [ key ] = this [ key ] ; } for ( key in features ) { klass. prototype [ key ] = features [ key ] ; } return klass ; } ; Class. prototype . extend = function ( features ) { var oldProto , oldFunc , newFunc , func ; oldProto = new this ( 'noInit' ) ; var makeParent = function ( parent , current ) { return function ( ) { this . parent = parent ; return current. apply ( this , arguments ) ; } ; } ; for ( var key in features ) { oldFunc = oldProto [ key ] ; newFunc = features [ key ] ; if ( typeof oldFunc != 'function' || typeof newFunc != 'function' ) { func = newFunc ; } else { func = makeParent ( oldFunc , newFunc ) ; } oldProto [ key ] = func ; } return new Class ( oldProto ) ; } ; Class. prototype . implement = function ( features ) { for ( var key in features ) { this . prototype [ key ] = features [ key ] ; } } ;

The above gives you a simple way to create prototypal inheritance in your Javascript. This approach is a simplification of the approach used in MooTools, and has been working well for me in everyday use. A sample use is :

var Person = new Class ( { name : null , init : function ( name ) { this . name = name ; } , sayHi : function ( ) { alert ( this . name ) } } ) ; var bob = new Person ( 'bob' ) ; bob. sayHi ( ) ; //alerts 'bob' var Ninja = Person. extend ( { weapon : null , init : function ( name , weapon ) { this . parent ( name ) ; this . weapon = weapon ; } , strike : function ( ) { alert ( this . name + ' strikes with ' + this . weapon ) ; } } ) ; var shinobi = new Ninja ( 'ryu' , 'shuriken' ) ; shinobi. sayHi ( ) ; //alerts 'ryu' shinobi. strike ( ) ; //alerts 'ryu strikes with shuriken' Ninja. implement ( { dodge : function ( ) { alert ( 'dodged!' ) ; } } ) ; shinobi. dodge ( ) ; //alerts 'dodged'

So there you go, a simple example of using inheritance and the idea of classes to contain functions together. In addition there was an example of using Class.implement to tack features onto existing instances. Now classes based on prototypes are just one approach to creating and grouping related code. Another is to use closures, but closures are an entire subject on their own. So I hope that this helps with understanding javascript a bit. I hope to do more articles covering some of more of the interesting parts of Javascript including closures and creating inheritance and private members with closures, binding, and a pattern I’ve been using for organizing Javascript that has been working well for me.