2010-11-16

Some Classes in JavaScript

I did some client-side coding using MooTools. There, as a long-time Java developer, I liked the way I could define classes like in some more object oriented languages:


var Vehicle = new Class({
drive : function() {
console.log("I'm driving a " + this + " with a top speed of " + this.topSpeed);
},
});
var Car = new Class({
Extends : Vehicle,

topSpeed : 250,

initialize : function(make, model) {
this.make = make;
this.model = model;
},

toString : function() {
return this.make + " " + this.model;
},
});
new Car("Fjord", "Taunus").drive();


Then I went on to server-side JavaScript, namely on node.js. There I immediately felt a bit weak without the Class() constructor. I did some googling to see if I could have Mootools on server-side too, but got under the impression that it's not that easy, requiring some customization of Mootools. Hence, I decided to roll my own. And here it is:



function Class(props) {
function copyProperties(from, to) {
for (var key in from) {
to[key] = from[key];
}
}
var constructor = function() {
props.initialize.apply(this, arguments);
};
if (props.Extends) {
copyProperties(props.Extends.prototype, constructor.prototype);
}
copyProperties(props, constructor.prototype);
return constructor;
}



That's not so much code after all, is it? The code in the first snippet actually works with my Class constructor. As you can see, it supports subclassing using 'Extends', a constructor named 'initialize' and any number of methods and properties.


It took me a couple of hours to get these roughly 10 lines of code together though. I had to realise that


  1. The "class" is actually a constructor function. Hence,  the Class() function has to return a constructor
  2. In any Javascript function, you have an "arguments" array (well not stricly an array but..) that you can use to access all arguments
  3. You can call any Function using its apply function with the "this" object and a list of arguments
  4. You can easily copy properties of an object by looping them using "for key in object"
I have to admit that I'm still a bit confused how this all works though :)

Feel free to prove my über-simple class system wrong and point me back to the correct path.