Here’s a coding style tip for writing more readable object-oriented JavaScript… What follows is a technique for writing OO JavaScript that is a bit more similar to what you see in more purely OO languages like Java or Python. This technique can (sometimes) lead to more sensible, readable JavaScript code.
To some of you this will be old news, as its certainly not an original idea. The first time I saw this technique was a few years back in some Gecko JavaScript source code, and I was pretty blown away. It had never occurred to me to write JavaScript this way… and I thought it was neat.
So we all know that JavaScript has a literal syntax for arrays and objects (very similar to Python arrays and dictionaries).
Arrays:
Objects (JavaScript terminology for dictionary, associative array, or name-value pair):
var myObject = {name: "Tod" };
Note that unlike Python dictionaries, with JavaScript objects you do not place quotes around the names in name-value pairs… a small, but important distinction.
Also note that like Python, JavaScript functions are data… and also have a literal syntax. Therefore you can add them to your object literal instances:
var myObject = {name: "Tod", toString: function () { return "Person ( " + this.name + " )";} };
This object literal syntax can be very useful for one-off objects. However, if you plan on creating multiple object instances from a single "prototype", you’re probably better off defining a JavaScript "class" using a constructor function and some instance methods on the constructor function’s prototype:
function Person(name) {
this.name = name;
}
Person.prototype.toString = function () {
return "Person ( " + this.name + " )";
};
So there you have your typical JavaScript "class definition". It just looks a little weird, doesn’t it? It’s kinda hard to tell just by glancing that the toString method is an instance method of the class who’s constructor is placed above. But that’s just the way JavaScript works.
Actually, there is something of an alternative to this syntax. But the alternative has its benefits and drawbacks. Remember our object literal syntax above? How about we add some whitespace and make it look a little more Java-esque?
var myObject = {
name: "Tod",
toString: function () {
return "Person ( " + this.name + " )";
}
};
One problem with this change is that our object is now a one-off instance of its type… we have no constructor function, and no means of creating additional instances. That’s ok… we can fix that too, by breaking the object into a constructor function and a prototype definition. That way, we get most of the readability benefits of the more Java-like class syntax, but still have a constructor for creating additional instances later:
function Person(name) {
this.name = name;
}
Person.prototype = {
toString: function () {
return "Person ( " + this.name + " )";
},
getName = function () {
return name;
},
someOtherMethod = function () {
...
}
};
var me = new Person("Tod");
I don’t know if anyone else is impressed by this, but the first time I came across it, I was pretty psyched. Note the important commas (,) after every instance variable or instance method. You will need those to avoid a JavaScript syntax error.
There are, however, drawbacks to this technique… Including the Person class in a type hierarchy is not possible with this syntax AFAIK (would love to be proved wrong there). Normally, to declare a subtype of an existing type in JavaScript, you do this:
Developer.prototype = new Person();
// next line fixes a little known problem in JS hierarchies...
// saw this explained in O'Reilly ActionScript book
Developer.prototype.constructor = Developer;
function Developer(faveLang) {
this.faveLang = faveLang;
}
Developer.prototype.getFaveLang = function () {
return this.faveLang;
};
Now Developer is a subtype of Person. I don’t know of anyway to achieve both the alternative syntax displayed above (in the Person class) and the subclassing functionality shown here with Developer on line 1. Any ideas?
(keep in mind that i’m not necessarily advocating the use of accessor methods in JavaScript here… the code is just meant to be an example)
Anyway… again, I know this is old news to many of you JavaScript bad-asses out there… but I hope that some of you guys can use this technique to make OO JavaScript a little more fun.