Perfection kills

Exploring Javascript by example

Archives Posts

Namespacing made easy

January 30th, 2008 by kangax

Enumerable#inject is one scary method. It took me a while to understand the beauty of this functional programming paradigm. Just in case you were ever wondering about its real life usage – here’s one of them.

We all know that using namespaces is generally a wise thing to do. You don’t have to create a multi level object structure, but nesting your code under a pseudo-namespace is what makes maintenance, upgrades and migrations somewhat easier and error-prone.

Few popular javascript libraries implement some sort of a utility function that automatically creates nested objects. What it means is that instead of writing it manually, you could let the helper handle it for you:

 
// creating nested structure manually is painful
var com = {
  thinkweb2: {
    projects: {
      _prototype: 'a deeply nested property...'
    }
  }
}
 
com.thinkweb2.projects._prototype // => 'a deeply nested property...'

Well, it appears that inject can handle such task in only 3 lines of code:

 
'com.thinkweb2.projects.prototype'.split('.').inject(window, function(parent, child) {
  var o = parent[child] = { }; return o;
})
 
Object.inspect(com.thinkweb2.projects.prototype) // => "[object Object]"

Not bad – a completely generic namespacing snippet.

What’s happening here is not a black magic. Inject accepts initial object as a first argument (in this case – window object) and iterator function as the second argument. It then calls iterator function on each item from the collection (in our case it’s simply a string split into an array). Iterator function receives accumulated result as a first argument and current value as a second. Iterator performs an action (creates a nested object) and returns accumulated result (the newly created parent object) to be used in following iterations.

Alternatively, we could wrap this all nicely and define as a String.prototype method:

 
String.prototype.namespace = function(separator){
  this.split(separator || '.').inject(window, function(parent, child) {
    var o = parent[child] = { }; return o;
  })
}
 
foo.bar.baz.quux = 'Nothing special...'; // => ERROR: foo is not defined
 
// Default separator is '.'
'foo.bar.baz.quux'.namespace();
 
foo.bar.baz.quux = 'Nothing special...'; // => "Nothing special..."
 
// Or using a custom one
'MY_AWESOME_APPLICATION::util::DOM::dimensions'.namespace('::');
 
'dimensions' in MY_AWESOME_APPLICATION.util.DOM; // => true

Note how we use “separator” argument (or defaulting to ‘.’) making the function somewhat more flexible.

P.S.
Heavy namespacing could lead to unnecessary complexity.
Lack of it – to buggy behavior.
In the end, the only thing that matters is what works best for you.

Enjoy!

Filed under inject having 17 Comments »

Archives Posts

Prototype 1.6.0.2 Cheat Sheet

January 22nd, 2008 by kangax

Prototype 1.6+ cheat sheet

A long awaited Prototype cheat sheet – a full reference to a bleeding edge 1.6.0.2 is finally here. I had no experience creating something like this before, so any bugs or suggestions are very much appreciated. Couple of notes about notations:

  • Modules are sorted in a somewhat logical order – those commonly used are mostly in the left/center area, while deprecated/utility methods are all the way to the right
  • Method can be recognized by parentheses following it (anything that doesn’t have ones is a property)
  • Deprecated items are marked red and have NO parentheses/arguments specified
  • Prototype extends quite few native objects’ prototypes with a set of convenient methods. In such cases there’s an explicit note about it next to a module name – i.g. stripScripts() method from “String (String.prototype)” can be called as 'foo'.stripScripts()
  • When a module is also a class, there’s a “(constructor)” note next to it – i.g. “Hash (constructor)” means that it should be called as new Hash()
  • There are few bonus items (such as those from Prototype.Browser) which are not yet included in documentation

Download (44159 downloads) and Enjoy!

Update:
I have managed to choose the most retarded format for the cheat sheet – almost squared – which was impossible to print or navigate. Sincere apologies. There is an updated version at the same address which also fixes few other annoyances:

  • Ajax.Responders is now a separate section
  • Added missing Event.fire
  • Added Prototype.BrowserFeatures.XPath
  • Added simple “Dimensions/Offsets” diagram
  • Minor rearrangements

Update 2:
Uploaded a Higher Contrast version (7657 downloads)
Seems to look much better when printed.

Filed under cheat sheet having 134 Comments »