[Fjord is hiring! Check out Web Enthusiasts Need Apply and Web Enthusiasts Need Apply, part 2 for details.]

I like the prototype.js javascript library. It’s a great and convenient library for web applications, particularly when used in conjunction with Ruby on Rails which in fact ships with it as well as script.aculo.us, a visual effects library built on top of it. I also liked Gary Haran’s talk at Montreal on Rails the other day, Gary’s a great technical speaker and has a knack for explaining things simply and concisely.

With respect to the use of prototype.js however, there are some caveats. In particular, it shouldn’t be used if you’re writing widgets or any javascript that you would like others to embed on another website. For instance, web applications meant for mashing up. There are 2 reasons:

  1. prototype.js is opinionated and doesn’t try to nor encourage namespacing, so co-existence with other frameworks/libraries. If you’re building something for inclusion in another site where you cannot control the choice of javascript conventions used, you are potentially breaking the rest of the site.
  2. prototype.js adds methods to the prototype of Array (javascript’s associative array), and there is code out there (like e.g., the site where your code might be included) that relies on being able to iterate over elements of an associative array by just doing “for (var element in my_hash) { ... }”. If you really want to see the potential impact of this and you’re feeling particularly masochistic, open up script.aculo.us in Firefox, turn on Firebug, and type and run the following snippet in the console (note that the script.aculo.us site loads prototype.js):

var foo = new Array();
foo['blah'] = 'blahaaaa';
for (var element in foo) {
    alert(element);
}

There is also a third but in my opinion less important reason: prototype.js defines $ (the dollar sign) and $$ (the double dollar sign), but according to the ECMA-262 on page 14, “the dollar sign is intended for use only in mechanically generated code.” Personally, though, I think that ignoring the standard here is fine (it’s not a very clearly written standard to begin with).

Also, since prototype.js has hit the mainstream, people seem to increasingly believe that it gives you classes and inheritance. Only half of this widespread belief is actually true. First, while it does give you the notion of a “Class,” all you’re really getting is the ability to define the constructor code inside an “initialize” method defined in the class’ prototype. For instance, here’s how I’d define a prototype.js style Class without prototype.js in pure javascript:


var MyClass = function() {
    this.abc = 1;
    this.def = 2;
}
MyClass.prototype = {
    methodone: function() {
        this.abc = 5;
    },
    methodtwo: function() {
        this.def = 6;
    }
}

With prototype.js, the above code looks like this:


var MyClass = Class.create();
MyClass.prototype = {
    initialize: function() {
        this.abc = 1;
        this.def = 2;
    },
    methodone: function() {
        this.abc = 5;
    },
    methodtwo: function() {
        this.def = 6;
    }
}

Second, the Object.extend() that prototype.js defines is not really an implementation of inheritance. Rather, it is an implementation of object augmentation. Object augmentation is when you have an object, like for instance MyClass.prototype from the example above, and you’re copying key value pairs from another object into it, so that MyClass.prototype is then augmented by that other object and, consequently, objects constructed with “new MyClass()” get access to their newly augmented prototype. What this doesn’t give you, though, is the ability to chain method calls across the inheritance chain. In an actual inheritance model, you’ll really have two separate objects with references from one to the other so that you can optionally invoke methods of the parent from the child (this is what “super” does in most OO languages).

Now is the lack of real inheritance a big deal? Perhaps not. Perhaps you can get away with just object augmentation in the vast majority of cases. But the distinction between inheritance and object augmentation is more than academic. For example, when you’re using augmentation you must make sure to not augment an object without being aware of every other piece of code that is augmenting that same object, otherwise you risk overwriting someone else’s freshly added methods. In a true inheritance model, you can relatively safely inherit from the same object from many different places without having to worry about overwriting methods defined by another inheritor (is that even a word, inheritor? :-))

It is worth noting that Yahoo’s excellent BSD-licensed (free!) and extremely well documented YUI library not only cares about namespacing (and so co-existence with other libraries), but also gives you both YAHOO.lang.augment() and YAHOO.lang.extend() which do object augmentation and prototypical inheritance. Since we’re on the subject, I’d also highly recommend the following Douglas Crockford talks from the YUI Theater: “The JavaScript Programming Language,” “An Inconvenient API: The Theory of the DOM,” and “Advanced JavaScript.” All of these, and more, are available for free at the YUI Theater.

[P.S.: Fjord is hiring! Check out Web Enthusiasts Need Apply and Web Enthusiasts Need Apply, part 2 for details.]

2 Responses to “When prototype.js is Inappropriate”

  1. Jon Says:

    He’s back, baybeh! And talkin’ computer jargon that only 0.00000004% of the population of the planet could understand! WOOO!! :)

    Nice to see you’re up and running man!

  2. Bosko Says:

    haha, hey Ouims!

Sorry, comments are closed for this article.