myWidget.doSomeStuff() if you don’t have an instance of
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?
Observe (using our suggested example above):
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
- …only to find out that it’s not even the right object for the task! [↩]
- For the record, I’m a Java neophyte; this is the comparison explained to me, and the one that makes sense. [↩]
- But now we’re just talking “best practices”. [↩]
- We’re (of course?) assuming here that there is a 1:1 binding relationship between editors and widgets for the sake of this example. [↩]
- 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). [↩]
- That is to say, if you think
thisis an instance, then you’d be mistaken—and you’d be missing the whole point of trying this method in the first place. [↩]
- …and for maximum effectiveness probably should. [↩]
- But when aren’t the arguments important…? [↩]
About Rob FrieselSoftware 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 →
“but this might not be what you think it is”
But yes, that’s also the resonant chord. “Be careful about ‘this’ and if you’re going to try this technique, be doubly careful.”