Simple Metaprogramming With Javascript

The more I’m messing around with Rhino the more I like it and in the process I’m learning more nifty Javascript tricks to use on my web based projects. For example, did you know that Javascript has features that facilitate quite effective metaprogramming? Let me give you a short example. Try this in your rhino console:

js> foo = "bar";
js> function bar() { print("baz"); }
js> this["foo"];
bar
js> this[foo]();
baz

In Javascript, fields and functions are implemented as associative arrays. In the example above, this returns rhino’s global object. All the functions and variables defined out of context of an object belong to it. Note how I can access the foo variable by using a string. I can use a simillar notation to call a function as well.

This means we can dynamically decide which function and/or variable is to be accessed at runtime using a very simple syntax without falling back on things like reflection or the Javascript eval() function. This works exactly the same when working within a browser – the only difference is that the top level element is called window.

To put this in context, let’s consider we have bunch of HTML elements on the page. each of them is supposed to trigger a slightly different action. We could naturally create a separate function for each, and then attach an appropriate onClick attribute to each. But perhaps a slightly cleaner method would be to use a single fuction for all of them. You could use something like:

onClick="return process_click(this);"

Then we can construct this function like so:

function process_click(elem)
{
	window[elem.name + "_action"](elem.value);
}

This way, every element will cause a function named with it’s name attributed and _action suffix, and take the value as the attribute. A single line let us build a rather concise, and easily extendable setup. For example checkbox named foo will invoke function foo_action().

Not only are we accomplishing a complex functionality with minimal work we are also enforcing consistent naming convention for the functions. If we manually pended the onClick function on each clickable HTML element we could vary the names significantly.

Now let’s say we need to store the output of this function in some text box on the page. That box can be part of a form called myform and it’s name could be the element name with a prefix of _calculated.

function process_click(elem)
{
	document.myform["calculated_" + elem.name].value = [elem.name + "_action"](elem.value);
}

You can create generic functions which manipulate different sets of variables and/or other functions based on the input values with minimum of code and effort. Sky is the limit here. :)

Yes, this is probably a tad contrived example. I don’t claim to be a Javascript expert. In fact this is one of those little hidden nuggets of knowledge that I uncovered very recently after I started messing around with the language. In the past I treated it mostly as a client-side, dumbed down version of Java that is mostly useful for making eye-candy fluffy client side stuff, and asynchronous calls to the server. That’s what I thought, and that’s how I used it. Now I’m begging to see that it is really a powerful dynamic language almost on par with Ruby or Python when it comes to expressibility and feature set.

Rhino framework actually makes it a viable language in and off itself, not mentioning giving you an awesome interactive console you can use for testing and debugging. I really can’t believe I had this really powerful language within my grasp all this time, and never really realized it.

[tags]metaprogramming, javascript, rhino, java[/tags]

This entry was posted in programming and tagged . Bookmark the permalink.



4 Responses to Simple Metaprogramming With Javascript

  1. jambarama UNITED STATES Mozilla Firefox Windows Terminalist says:

    Alright, that’s it. I’m installing Rhino and I’ll make time to tinker with it. I’m a Yegge follower as well (apart from his emacs fixation – Vi rule!), but he’s always got some new thing he’s pushing, and I never know if it is worth investigating myself.

    Well, you’ve convinced me!

    Reply  |  Quote
  2. Luke Maciak UNITED STATES Mozilla Firefox Windows Terminalist says:

    You know, a lot of people who I consider to be really smart use vi.

    Funny thing is that the profoundly brilliant people that I considered mentors, or inspirational figures me tended to have the Emacs fixation.

    I don’t know if there is a relationship here but… Well, I started using Emacs at some point because of that. I still use vi much more but both editors are great in their own way. :)

    Reply  |  Quote
  3. Luke Maciak UNITED STATES Mozilla Firefox Windows Terminalist says:

    Also, Yegge seems to be fairly consistent as to what he looks for in a language. His jumping from platform to platform seems to be simply refining – picking the best dynamic, duck typed, readable, expressible language to date. :)

    Reply  |  Quote
  4. Starhawk UNITED STATES Mozilla Firefox Windows says:

    Pretty cool :)

    The first time I read this i skimmed it and didn’t really get what you were saying. But now i think i see it kinda like function pointers in C, no? Hmm a lot easier too. haha.

    I believe I need to learn more advanced JS stuff. Maybe Rhino too but I’ve been trying to stay away from trying to learn every cool thing that comes around. lol.

    Reply  |  Quote

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>