At first, it was mysterious and stylish, then it became regular, and now it’s just mundane! The usage of “self-invoking anonymous functions” is what I’m talking about. You know what I mean; it’s this:
(function(){ // I'm cool })(); |
Recently, I even managed to convince my poor brain that using many of these constructs amounted to maintainable and cool-looking code. I even thought that this:
function Constructor() { } Constructor.prototype.fn = function(){}; |
… was ugly enough to require a bit of self-invoking cool’ness:
var Constructor = (function(){ function Constructor() { } Constructor.prototype.fn = function(){}; return Constructor; })(); |
What was I thinking?? … Well, I’ll tell you: I was trying to create the illusion of containment! I didn’t want the fn
method declaration to be left astray, departed from its parent (the constructor).
When used in this way, the Self Invoking… cool’ness creates an entirely pointless closure, that only serves to comfort the human programmer. Its similar to this:
var fruits = "banana apple orange grape strawberry".split(' '); |
Compared with the less-cool more-logical version:
var fruits = ['banana', 'apple', 'orange', 'grape', 'strawberry']; |
So, they both end up exactly the same, but the former takes a while longer to actually produce the array upon interpretation. So, why exactly do we do this?
I know why I do it: it’s because I’m lazy; so lazy that I can’t even bring myself to type out an array of strings, even though doing so would result in a faster run-time! The cost of repeatedly reaching for the awkwardly placed '
or "
on my keyboard, to type out the array, is obviously just too much for me to bare!
Maybe you don’t do it… but it is out there!
// From jQuery 1.3.2 "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(",") |
Let’s compare that to the typed out array:
['ajaxStart','ajaxStop','ajaxComplete','ajaxError','ajaxSuccess','ajaxSend'] |
By typing it out the former “cool” way we save a total of ONE character! Worth it?
Do you have any “anti-patterns in the making” to share?
Note: Obviously, there are situations where a self-invoking cool’ness (what I will call them from now on) might be useful. For example, the module pattern, or that ol’ (function($){})(jQuery);
trick.
Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!
I do believe self-executing functions have a place and a purpose and they carry out that purpose well. But I agree that their once esoteric appearance has now become the “in thing” to do, even when there is no actual point in using it.
I’ll be honest though, I don’t think I’ve EVER been so lazy I couldn’t type out a proper Array! π
Thanks for the article. I have too lazy to type out an array on occasion, but I now have a macro that will turn “this, that, the other” into [“this”, “that”, “the other”]. In some ways, being lazy is an art form. π
Andrea Giammarchi was just ranting about how much people avoid the with statement but do things like what you just pointed out:
http://webreflection.blogspot.com/2009/12/with-worlds-most-misunderstood.html
I have to admit that I am guilty of doing exactly this. I think JS just needs a “let” expression similar to Lisp’s (very different from the JS 1.8 “let” statement).
I often do the self invoking function thing on returns when I can’t squeeze a “return foo ? bar : baz;” in there instead. I think in those cases it is acceptable (though I have definitely misused self invoking functions plenty).
Hmmm, I think the string split example is easier to type and maintain so I would choose it for those reasons.
The self invoking function pattern does get misused by people who don’t really understand what it does, but it is popular for a good reason; @nick the example may be out of context but if it was standalone then it would prevent a global variable, which is a real benefit.
Having looked at the Andrea Giammarchi example use of ‘with’ I notice it has a very dubious reliance on the implied end-of-line semi-colon, I’d run a mile from that π
@Pete,
I believe that Andrea’s point was not that self invoking functions are inherently “bad”, but that they have their use cases. Many people (myself included) have used or do use self invoking functions to avoid polluting whichever namespace they are inside (which is great when in the global scope, as you and many others will point out). Often times, you can achieve the same thing with less code, and without creating an unnecessary closure by using the with statement.
If I were to boil it down to the essence (apologies to Andrea if I butcher anything): Every trick can be used or misused (self invoking functions and with), but that doesn’t mean we should blindly refuse to use one or the other, but that we should think about which will be best for the current situation.
@Pete,
I know “what it does”, but I’m the first to say that I misuse it quite a lot.
Also, it’s quite difficult to know what classes as “misuse”. Say, for example, I have to prepare a value – this only needs to happen once – but the preparation of this value is complex, and would certainly complicate the surrounding code if left un-contained. In such a situation I would use the mentioned construct to provide such containment.
@Nick, what sucks is that the
with
statement has been deprecated in ES5. It’s a classic case of punishing the whole class because a couple kids mess around. Sure, thewith
statement can be misused, but it can also be used to great effect.