Thursday, April 22, 2010

Easy Breezy Javascript OOP

Javascript does not support classical OOP. Instead it supports prototypal inheritance. It seems that everybody still wants to use the classical OOP pattern though and I don't really blame them. I use it all the time in my own projects and I see it used in many of the libraries and frameworks out there. Some people think that classical OOP has no place in Javascript, but I and many others respectfully disagree.

Despite the numerous tutorials on the web, many people still ask what is the proper way to do classical OOP. I'm not sure if the issue is the quality of the tutorials or the myriad of ways to simulate classes. In any case, I feel that there is room for one more quick tutorial. I do not claim this way to be the "proper" way, but I do feel that it is a "good" way. Many people and libraries/frameworks use this pattern or something very close to it

Classes and the Constructor

Defining a class and it's constructor function is easy. It looks like this:

// create a class called Animal
var Animal = function(name, age) { 
    // assign the passed-in arguments to instance members
    this.name = name; 
    this.age = age;
};

Using this class is also easy:

// create an instance and assign it to the pet variable
var pet = new Animal("Spot", 2);

Instance Methods

To add an instance method, you want to use the prototype property. It looks like this:

// create an instance method called "sayHello"
Animal.prototype.sayHello = function() {
    // access instance members using the "this" keyword
    return this.name + " doesn't speak.";
};

To use an instance method, you can simply call it on the instance:

// make the animal say hello
pet.sayHello(); // returns "Spot doesn't speak."

Static Methods

Static methods are applied to directly to the class like so:

// create a static method called "getName"
Animal.getName = function(animal) {
    // return the name of the passed-in animal
    return animal.name;
};

When using a static method, you use the class:

// call the static method
Animal.getName(pet); // returns "Spot"

Subclassing

This is usually the sticky point and where many implementations differ slightly (or not-so-slightly). Like I said, I think the way I present is a good way though. It requires one little helper function.

var extend = function(subClass, parentClass) {
    var tempFn = function() {};
    tempFn.prototype = parentClass.prototype;
    subClass.prototype = new tempFn();
    subClass.prototype.constructor = subClass;
    subClass.superclass = parentClass.prototype;
};

The what, why and how are beyond the scope of this article, but I certainly encourage you to do deeper digging if you are so inclined. Using the function is rather easy though.

// create a new class called "Dog"
var Dog = function(name, age) {
    // call the constructor of the superclass
    Dog.superclass.constructor.call(this, name, age);
};

// explicitly make Dog subclass Animal
extend(Dog, Animal);

Instance Methods

To add new instance methods, just add them to the prototype of the subclass:

// create an instance method called "bark"
Dog.prototype.bark = function() {
    return "Woof!";
};

To override instance methods, and to call superclass methods, do this:

// override the instance method called "sayHello"
Dog.prototype.sayHello = function() {
    if (this.age < 1) {
        // call the super "sayHello" method
        return Dog.superclass.sayHello.call(this);
    }
    else {
        return this.bark();
    }
}

Using instance methods on the subclass works exactly like before:

var petDog = new Dog("Spot", 2);

// make the animal say hello
petDog.sayHello(); // returns "Woof!"

That's really about it. It's simple and doesn't include many things like interfaces or private members, but it works. And that's how you do easy breezy Javascript OOP.

Wednesday, April 14, 2010

Introducing Yabble!

A few months ago I started working with Node.js, and by extension, CommonJS. Since then I've become fascinated with the goals of CommonJS and wanted to get involved. CommonJS is mostly suited for the server-side environment, but it does not exclude browsers. There are even a number of frameworks/libraries out there using it in the browser space such as SproutCore, Narwhal, and RequireJS. However, these don't really fullfill the need for a simple, barebones CommonJS module loader for the browser. SproutCore and Narwhal are great, and come with a ton of goodies, but oftentimes all of those goodies are not needed. RequireJS fits more closely with my goals, but still doesn't quite fill the niche that I'm after. Enter Yabble.

Yabble is a general purpose browser-side CommonJS module loader. The goals are to be small, flexible and useful. There are numerous places where, when two paths exist, both were made available instead of choosing one.

XHR vs script tags

Many argue that using script tags for dynamic Javascript injection is preferable over XHR. I tend to agree. Script tags are usually easier to debug and support fetching cross-domain. However, in the CommonJS world, that means that the modules need to be wrapped in some boilerplate code (named a Transport). Since no server-side CommonJS module loader requires this wrapping, it is a pretty big disconnect between modules meant for the server-side and those meant for the browser. Ideally, a single module could be supported on both. With XHR and eval(), it is possible to retrieve the raw module code and "wrap" it on-the-fly. It is also harder to debug and doesn't often support cross-domain requests. So, Yabble supports both. The XHR and eval() method is the default one and I envision its use mostly for quick-and-dirty development efforts. The script tag method can always be used if the developer prefers and when the application is deployed to production.

Hand-wrapped vs auto-wrapped modules

It is possible for modules to be automatically wrapped in a Transport through a build process or some other means. However, some argue that hand-wrapping is the best way to go. I tend to disagree, but, there is nothing stopping anyone from hand-wrapping modules with the use of Yabble. For automatically wrapping, a build-time tool is included to analyze modules and wrap them. Another method is to use a server-side script to wrap and serve modules on demand.

Individual file loading vs packaged file loading

This isn't really a debate. In general, individual file loading is used during development and for deployment a single, packaged file is created to reduce the number of requests. Yabble supports multiple modules being defined in a single file without any additional instructions. In addition, file packaging support for the tooling is on the roadmap.


It is my sincere hope that many find this project useful in creating well-structured web applications. The more people jumping on the CommonJS bandwagon, the better.

For more information and to get the code, visit the project page.
To see it running live, visit the unit tests.

Tuesday, April 6, 2010

Creating A Javascript Function Inside A Loop

I see the following question asked quite often in #javascript: "I loop over an array of elements and attach an event handler to each one. I pass along an index/variable for such & such reason. The problem is, when the event handler is executed, the index/variable is wrong!"

Example:

for (var i = 0, n = elements.length; i<n; i++) {
  var el = elements[i];
  el.addEventListener('click', function() {
    doSomethingWith(i, el); // i, el are not what you expect!
  }, false);
}

The reason that this is true is somewhat complex, but in basic terms, the function is only actually created once (instead of once each iteration of the loop) and that one function points to the last known values of the variables it uses. For more reading, start with closures and maybe move on to the ECMA Specification, in particular section 13.2, point 1.

The fix to this problem is not too difficult. There is a specific pattern that can be used to ensure that each iteration of the loop creates a brand-new function with the correct values. I call this pattern a "generator function". It probably has a proper name, but I'm not aware of it. The basic idea is to define a function (the generator) which creates and returns functions with the proper variables defined, and then call that generator function for each iteration of the loop, passing in the appropriate values. A typical generator function looks like this:

(function(variable) {
  return function() {
    // do something with variable 
  }
})(value);

There are a few things to notice in this pattern. First is that there are two function expressions: an outer one and an inner one. The outer one is the generator function, and the inner one is the function that contains your original code. Secondly, the generator function expression is wrapped in parenthesis and immediately called with an input of "value". This means that the inner function can use the identifier "variable" and it will refer to whatever value was passed in. The result of this whole shebang is a brand-new function which uses whichever values were passed in to the generator.

Applying this concept to our original problem, we come up with:

for (var i = 0, n = elements.length; i<n; i++) {
  var el = elements[i];
  el.addEventListener('click', (function(i, el) { 
    return function() {
      doSomethingWith(i, el);
    }
  })(i, el), false);
}

It's quite close to the original code, but with a little bit of wrapping. Note that this pattern can be useful for more than just attaching event handlers, although in most cases some form of loop is involved.