Monday, May 10, 2010

Intuition When Using Closures

I got into a debate with somebody in #javascript today regarding closures: how they work, how they should work, and are they intuitive. This person had run into a problem similar to the one I posted about earlier. In any case, as the discussion was coming to a close, I created some examples which somebody suggested I blog about. Let's start with a simple piece of code that more or less shows the original problem.

var i = 0; 
el.onclick = function() { print(i); }; 
i++;

In the above example what will be printed? This person argued that, intuitively, "0" should be printed. Of course the correct answer is that "1" will be printed. I can understand how this may be confusing to someone new to Javascript. However, take another example:

var i = 0;
var func = function() { i++; };
func();
print(i);

If I were to show this piece of code to someone, they would probably say that it makes sense. Of couse "1" will be printed. It is intuitive (and correct). Following that line of reasoning:

var i = 0;
var func = function() { print(i); };
i++;
func();

This code also seems to make sense, especially in light of the previous example. The only real difference is that this example reads/prints the variable, and the previous one modified the variable. In both cases "1" will be printed.

Now we're back to the original code:

var i = 0; 
el.onclick = function() { print(i); }; 
i++;

Note that the only difference between this piece of code and the previous one is when the function is executed. In one the function is executed right away, in the other the function is executed as a click handler. In both cases i++ occurs first and in both cases "1" is printed. This is consistent behavior and somewhat shows how closures can morph from something which "just makes sense" into something that isn't quite as intuitive.

The reason for this behavior is that closures work by pointing to the original variable by reference, if you will, not by value - even for primitives. So when the anonymous function runs, i is still pointing back to the original i which has been incremented to 1.

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.