found drama

get oblique

faking it: static method calls in JavaScript

by Rob Friesel

Have you ever wanted (as an object-oriented JavaScript developer) to work with an object before you had an instance of it? For example, perhaps there’s a method that you would like to call without going through the overhead of instantiating the object1. How would you go about doing this? Can you invoke myWidget.doSomeStuff() if you don’t have an instance of myWidget yet? Do we have static methods in JavaScript like we do in (for example) Java2? (HINT: the short answer is “not exactly”.)

First: what are the more traditional options?

A global function. If the mechanics of the function are not specific to the object’s implementation, then this might be a perfectly acceptable approach. If your function is just “doing stuff to” (or “…with”) some arguments then this might be fine. Performing some mathematical operations? Who needs an object-oriented approach for determining Fibonacci numbers? Or trimming whitespace from strings? Certainly that would be overkill.

A namespaced util method. Not too dissimilar from the global function approach; but if you’re namespacing, you’re less likely to have collisions in your variable and function names, and maybe some better sharing of common code, etc3. As far as “static methods” go, we’re just calling these methods off a singleton—fine (for example) for converting constants, or otherwise working with and manipulating known quantities.

But what about something more sophisticated? What if you have a family of classes (e.g., widget editors) that are all related but may each require an ever so slightly different approach to the context inspection? A global function or namespaced util won’t quite cut it here. What are we to do?

Now it turns out that JavaScript’s prototypal inheritance apparatus provides us with a way to do this. Depending on how you’ve designed and implemented your object classes4, this could be a relatively trivial operation.

Observe (using our suggested example above):

Nifty, eh?

Imagine a scenario where you have a few dozen classes like this (e.g., each class representing an editor for a specific widget that you might deploy to your WordPress-based blog)—using this technique, each class could perform its own inspection of the context (e.g., the DOM fragment representing the widget) and depending on the outcome of the inspection, assign itself as the appropriate handler5—and all without creating an instance of a given class until it is needed6. Marvelous!

But this approach is not without some dangers7 and does require careful attention to detail and some discipline. Because you’re invoking the specified method from the prototype, you should assume that the method is not “scope safe”. This is not to say that this is unsafe; but this might not be what you think it is8. You can9 still tap into this in your “static” method, but you better be damn certain that your this is what you need it to be and that whatever it is you’re trying to access was declared as part of that object’s prototype. As for the method itself, the arguments passed to the function become of critical importance10 for how the method returns. But, if you are aware of the possible scope issues, and engineer the “static” method in such a way that it is sufficiently scope agnostic, then invoking methods from the prototype in this manner can be a powerful technique to add to your JavaScript repertoire.

  1. …only to find out that it’s not even the right object for the task! []
  2. For the record, I’m a Java neophyte; this is the comparison explained to me, and the one that makes sense. []
  3. But now we’re just talking “best practices”. []
  4. I won’t go into prototypal inheritance and the various JavaScript constructor patterns here—it’s too big of a subject for this footnote (or even this particular blog post). However, may I recommend familiarizing yourself with “parasitic combination inheritance”, which you may recognize as the extend() method from frameworks such as Ext JS or YUI. For a great overview of inheritance and constructor patterns, may I recommend chapter 6 of Nicholas Zakas’ Professional JavaScript for Web Developers []
  5. We’re (of course?) assuming here that there is a 1:1 binding relationship between editors and widgets for the sake of this example. []
  6. Granted, in this example, there still needs to be some apparatus in place to manage calling the inspector method from each prototype (bringing us right back around to the “global function and/or namespaced util” question) but depending on the specifics of the implementation, there’s actually an opportunity to cache or curry the results from the inspection. And/but this is not at all to diminish the huge advantage you get from having the class’ method actually on the class; everything you need to know about the class is that it exists (and it takes care of the rest). []
  7. As many JavaScript developers have discovered by their “journeyman” stage, messing around with the prototype of a given object is not for the faint of heart. []
  8. That is to say, if you think this is an instance, then you’d be mistaken—and you’d be missing the whole point of trying this method in the first place. []
  9. …and for maximum effectiveness probably should. []
  10. But when aren’t the arguments important…? []

About Rob Friesel

Software engineer by day, science fiction writer by night. Author of The PhantomJS Cookbook and a short story in Please Do Not Remove. View all posts by Rob Friesel →

3 Responses to faking it: static method calls in JavaScript

fogus says:

“but this might not be what you think it is”

It never is. Either Javascript’s notion of this is broken, or I am. The jury is still out.

found_drama says:

@fogus- I’m not here to pass judgment on JavaScript’s implementation of “this”—that it’s so easily muddled is probably sufficient evidence that it’s fundamentally flawed (to say nothing of how many times I’ve heard “it’s broken” from folks I respect). But with a little discipline even an obsessive dilettante (like me!) can make a half-way decent go of it and maybe even produce a decent piece of software.

But yes, that’s also the resonant chord. “Be careful about ‘this’ and if you’re going to try this technique, be doubly careful.”

Leave a Reply

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