Programmish
Posts Tagged prototype
Tracking Event Observers with Prototype

In my current day to day work I spend a lot of time writing Javascript, and a significant portion of that Javascript involves Events. Of course creating event observers is dead simple with Prototype, as is stopping event observers. For better or for worse Javascript isn’t C, and sometimes we lose track of which events we’re observing, and which we’ve cleared, and we start to create a fairly large Event.cache.

Stumbling across Juriy Zaytsev’s Event Counter Bookmarklet I decided to do a bit of debugging of an internal data analyst application current under development, and to my astonishment discovered that after a few minutes within the application I had nearly 4,000 Event observers hanging around. Granted, this application handles editing of rather complex documents, but something wasn’t getting cleaned out properly. After manually digging out the low hanging fruit, I had managed to drop half of those dangling observers, but I was still missing quite a few, and over time these smaller leaks were bound to bog down the application. I decided I needed a bookmarklet with a bit finer grain, that could enumerate the types of observers in the document. Building upon Juriy’s use of the inject method of Prototype Enumerables I built the following simple script:

javascript:alert(
    "Event Observersn" + $H(Event.cache).inject( $H(),
        function (acc, p) {
            $H(p.value).each(
                function (evtT) {
                    if ( !acc.get(evtT.key) )
                        acc.set(evtT.key, 0);
                    acc.set(evtT.key,
                        acc.get(evtT.key) + evtT.value.size()
                    );
                }
            );
            return acc;
        }
    ).inject( "",
        function (acc,p) {
            acc += "n"
                + p.key
                + ":"
                + ( " ".times(40 - p.key.length) )
                + p.value;
            return acc;
        }
    )
)

Which you can grab with this bookmarklet.
This bookmarklet produces a popup with an enumerated list of observers by type:

Bookmarklet Results

JavaScript Namespacing in 85 Characters

Anyone working with Javascript for any significant amount of time will probably run into the problem of namespace pollution, where a function (or a whole host of functions) defined in one library override those defined in another. With the proliferation of libraries that extend built in object Prototypes, this problem is extended to the basic behavior of objects acting in ways contrary to what we would expect. When this namespace pollution seeps into library functions and basic objects, it can cause incredibly pernicious problems that are difficult (if not impossible) to track down.

In any significantly useful library or application it’s impossible to completely avoid adding objects and functions to the global namespace, but a structured and sane approach is usually better than seeding objects throughout the global window object. Consider a simple Javascript file that we might load in a page:

var myValue = 42;

function foo() {
	alert("Hey there, it's foo.");
}

function bar() {
	alert("Hey there, it's bar.");
}

function baz() {
	alert("Hey there, it's baz.");
}

Once loaded we can directly access these three functions by name, as they’ve become part of the global namespace. If we were to load another file, with another function named “foo”, “bar”, or “baz”, we’d have a conflict where we attempted to define the same function in the global namespace twice.

A better approach would be to create our own namespace, and store our functions inside of this distinct object. We’d still be extending the global namespace, but only once, for our top level namespace object. This is far from a new idea. Some examples build namespacing using PrototypeJS (or one from Mark Ziesemer), some use the Yahoo API for namespaces. All of these have in common the same basic idea: bring module or package style namespacing familiar from other languages into JavaScript. The module/package structure allows us to create nested sets of classes and objects that can all be accessed from a single base object, so instead of putting all of our functions in the global namespace, as we did above, we could create a different structure to store our functions and data:

com.programmish.values.myValue = 42;

com.programmish.lib.foo = function() {
	alert("Hey there, it's foo.");
}

com.programmish.lib.bar = function() {
	alert("Hey there, it's bar.");
}

com.programmish.lib.baz = function() {
	alert("Hey there, it's baz.");
}

It’s a bit more code to write up front, but now we know our functions (and data) are isolated from other libraries or files we might load. The trick, with all of the namespacing solutions, is creating the namespace object heirarchy; the objects nested within objects. Here’s a simple version, using pure (no external libraries expected) JavaScript:

function N(namespace) {
    var pieces = namespace.split('.'), node = window, piece;
    while ( piece = pieces.shift() )
        node = !node[piece] ? node[piece] = {} : node[piece];
}

Rewriting our example from above using this namespacing function:

// create the 'values' namespace
N('com.programmish.value');

com.programmish.values.myValue = 42;

// create the 'lib' namespace
N('com.programmish.lib');

com.programmish.lib.foo = function() {
	alert("Hey there, it's foo.");
}

com.programmish.lib.bar = function() {
	alert("Hey there, it's bar.");
}

com.programmish.lib.baz = function() {
	alert("Hey there, it's baz.");
}

When we create a new namespace, any existing parts of that namespace that have already been created are left intact, with only new sections of the namespace created. This namespace code compacts nicely to 85 characters, which is plenty small to include in a top level script tag on any page:

function N(n){var p=n.split('.'),b=window,s;while(s=p.shift())b=!b[s]?b[s]={}:b[s];}

So please, use some form of JavaScript namespacing.