<< My Talk at The Ajax Experience | Home | Introduction to Reverse Ajax >>

$

There is a problem brewing for people that wish to use more than one Ajax library in the same page. It ought to be easy, but it's not...

Javascript has a problem - lack of language level namespacing / packaging. So if I write a web page that uses Javascript from 2 authors, both of whom defined a wibble() function, the result will probably be broken, and worse, since the second definition silently overwrites the first, the result will probably be silently broken. Rather than a compile/link error like in most languages, it will just blow up in your face at some stage.

According to Brendan Eich's Javascript talk, this problem is being fixed in Javascript2, but the Sun will be getting dim before all browsers support it enough that we can rely on it.

In the mean time the there is the very real danger of mid air collisions.

DWR has a $ function, copied from Prototype. So do Atlas and many other frameworks. Alex Russell says it is a very frequently requested feature for Dojo.

The $ function is the only function in DWR that isn't in an object based namespace. I'm not keen on it for this reason, but it is very useful: document.getElementById() is just such a mouthful.

But there is a problem:

  • When Prototype changes their definition of $, what is everyone else supposed to do?
  • What happens when Prototype's $ gets over written by a $ from another library without the new features?
  • What happens if another library want to add some feature that Prototype doesn't pick up?
  • What happens when to implementations of $ evolve in incompatible directions?

On one hand $ is a recipe for a mutual exclusion amongst Javascript libraries. It could mean that Prototype can't be used with anything but Script.aculo.us and other systems that go out of their way to evolve with it. Prototype's willingness to play with the "global scope" has caused bugs in DWR in the past that we have needed to provide work-arounds for, so it is a real problem.

On the other hand $ is very useful because you need to do it so often, and $ is something like 14 times less wearing on your keyboard than document.getElementById(). It's one of the sweetest bits of syntactical sugar there is for Javascript. The bad news is that the sugar is laced with another white powder that is both addictive and dangerous.

So here is my proposal:

Ajax library authors except Prototype should get together to define $ to mean basically document.getElementById() and nothing more. Each should do as DWR does and check for the existence of $ before defining it. Prototype on the other hand should not do the same check. Ever. Prototype should ensure that it's definition of $ is always a strict superset of the 'standard' definition.

DWR can be used with any version of Prototype because if Prototype gets declared first, it defines $ in it's superset form, and then as DWR is declared, it notices and does not alter the superset definition. If however DWR gets defined first, it will define $, however Prototype will overwrite the subset definition with it's superset definition.



Re: $

I don't like the idea of prototype getting special treatment. I personally have my own $ function, written a while before prototypes, but never publically released. It has somewhat different functionality: it's both cached and allows you to pass infinite arguments, any of which can be arrays or arrays of arrays, etc. You get back the same data configuration you pass in. A -lot- of my company's code is based on this. Personally we don't use any 3rd party frameworks, but for people in similiar situations that do: what, just oh well? Global namespace pollution is annoying but it won't really ever go away. I think it's up to the developer of the particular application to realize that namespace pollution exists, mainly because you can't count on every framework to even try and play well with others. If I ever publically release mine, for instance, there's no way I'd ever change the $ function. Tens of thousands of lines of code rely on it. You can't expect developers of other frameworks to change their code either.

Re: $

Why does $() need to be a global, at all? Is there some reason the <code>with</code> keyword isn't suitable in this situation?

var frobnicator = {
   wibble: function() { return 'frobnicated'
}

var caturgiator = {
   wibble: function() { return 'caturgiated'
}

with (frobnicator) {
   wibble()
}

Re: $

well WhateverFramework.$() isn't a whole lot better than document.getElementById. <p /> And if the framework has a really short name you're likely to override the entire thing since it -has- to be global.

Re: $

True, but as long as $() has been namespaced, you can easily promote it to a global.

var $ = WhateverFramework.$

And, depending on how you implement namespaces, you can still use the shorthand form within the framework.

function frobnicator() {
   if (typeof(frobnicator.namespace) == 'undefined') {
      function $(id)    { return document.getElementById(id) }
      function wibble() { $('report').innerHTML = "help i've been frobbed!" }
      frobnicator.namespace = {
         $:      $,
         wibble: wibble
      }
   }
   return frobnicator.namespace
}

with (frobnicator()) {
   wibble()
}

Re: $

One interesting thing Brendan Eich said in his keynote was that there might be a "use strict" pragma in JS v2. I assume this would catch function reassignments among other things. While it doesn't address recovery from the error when the src of the scripts is outside your control, it will certainly help to identify these otherwise silent issues.

Re: $

The most of text editors nowadays have some sort of code completion/ insight/ suggestion, so I don't find using cryptic short names as $() or $$() at all that cool or necessary. And it breaks one of the main rules of naming conventions, that class/function name should explain what it’s code does. Now prototype is so popular that everyone knows what $() means, but still it's a bad practice.. I personally would prefer having each lib packed in separate class, using that as namespace, same way we did in php. No conflicts that way, and far better self-explanatory of code, at the cost of just few extra characters.

Re: $

Pioneer-soft's framework has a simple solotion to Gloabal variables: http://cbsdf.com/technologies/DHTML-Widgets/Widget-samples.htm Append a unique string.

(Slightly off topic) Google Web Toolkit

Slightly off topic, but I'm wondering what Joe thinks of Google releasing it's web toolkit?

Javascript conflicts and portlet namespaces

Joe Walker (author of DWR - a remoting framework for javascript/java) blogs about one face of this problem here - the $ function