Monday, September 22, 2014

IIFE Mania

At work today, I noticed someone using an IIFE that was completely pointless. The only possible rationalization was, "I saw it on SO and don't really understand JavaScript." So, allow me to elucidate.

An IIFE creates a tidy new scope for you to do your magic in. This is especially good if you're creating modules.

Protecting Global Namespace

The scope created can act like a safety net to keep you from accidentally declaring global variables. Implied globals, however, slip right through. That's cool, but your linter should catch these mistakes.

non-IIFE

// blatant new global variable
var foo = 1;

// an implied global
bar = 1;

IIFE

(function () {
    // foo stays out of the global namespace
    var foo = 1;

    // implied globals are still global
    bar = 1;
}());

console.log(bar);

Passing Arguments

Perhaps my colleague thought passing arguments into his function provided some benefit. Though, the arguments passed in were globals we provide. It's not a $ conflict situation.

This is the aspect that really made me scratch my head.

Does passing arguments somehow protect them? No, because they're the same reference.

var foo = { original: true };

(function (localFoo) {
    console.log(localFoo === foo);  // true
    console.log(localFoo.original); // true
}(foo));


// evil code messing up our precious global
foo.original = false;

As long as your function executes before that other evil code messes with the global, you're good. But wait...

var foo = { original: true };

console.log(foo.original); // true

// evil code messing up our precious global
foo.original = false;

That gets you the same result since your code executed before the evil code.

What if you're trying to insulate the outside world from your changes to the globals?

var foo = { original: true };

(function (foo) {
    foo.original = false;
}(foo));

console.log(foo.original); // false

Oh, yeah. They're the same reference. There's no benefit to passing these in.

Why Ever Pass Arguments?

There are a few situations where it's a good idea to pass arguments into an IIFE.

Aliasing

If you want to use a different name for the global, that's cool. This is how jQuery gets around other libraries that use $. It's a nice way for you to pick what you want to call the global.

This example attempts a lame joke by reference.

var foo = { original: true };

(function (al) {
    console.log(al.original);
}(foo));

Super Fast Code

Another good time to pass arguments into your IIFE is when you've optimized every other frigging thing in your code and you just have to speed it up some more. Technically, providing the parameter creates a reference to the global variable inside the function's scope. That means, wherever your code references the global, it won't have to look up the scope chain until it finds it in the stratosphere.

That's kind of a stretch, though.

Conclusion

IIFEs have a proper place, including those with arguments. Primarily, it's to carve out a nice private chunk of scope for you to work in. If you're not declaring any variables or functions, you don't need this.

Passing arguments into an IIFE looks really cool like all the stuff you've seen online, but there aren't many reasons to do it. If you do it when it's pointless, it just makes you look like a jackass.

No comments:

Post a Comment