Saturday, September 13, 2008

method_missing in Javascript

method_missing in Javascript? Well not yet -- but you might be surprised to learn that some Javascript implementations already feature this functionality. For example, it appears that Mozilla based browsers have had __noSuchMethod__ since at least Javascript version 1.5. Also, it looks like this feature is quite possible to become a standard feature of Javascript in the future although not likely for 3.1. Look here for a couple of threads discussing this feature.

What might you do with a feature like this? If you found this page I imagine you already have a few ideas in mind but if not the Ruby on Rails framework contains many examples of this technique. Ruby on Rails uses Ruby's method_missing for all sorts of "meta-programming" magic like dynamic finders such as ActiveRecord::Base#find_by_login_and_password('bob', 'cheese').

So I can't leave you without an example...If your browser is so inclined, the following text box will allow you to enter any call you like against the "example" object and will use __noSuchMethod__ to spit back information about the call.






The code that sets up the "example" instance looks like this:

var example = {
__noSuchMethod__: function(id, args) {
alert("You called " + id + " on example with " + args.length + " arguments [" + args.join(",") + "]");
}
}
document.getElementById("evalButton").onclick = function() {
eval(document.getElementById("evalText").value);
}
view raw gistfile1.js hosted with ❤ by GitHub



I, for one, would really like to see a feature like this become a Javascript standard.

Hey, if you are interested in learning more about Javascript I would recommend the following books: Javascript: The Definitive Guide, Pro Javascript Techniques, and Prototype and script.aculo.us: You Never Knew JavaScript Could Do This!

Oh yeah, one last thing - since Javascript objects are pretty much just hashes this type of method missing technique really only needs hashes to be extended to allow a default value to be specified like you can do with a Ruby Hash. This would result in the possibility of writing code like this:

var example = new Hash(function() {
alert(arguments.callee + " called on example with " + arguments.length + " arguments ");
});
view raw gistfile1.js hosted with ❤ by GitHub


I'm not sure what type of syntax could be offered if the object didn't begin its life as a Hash.