Understanding Immediately-Invoked Function Expressions - Part 2
In the first part of this series we covered the basics of what an immediately-invoked function expression (IIFE) is and how it works using some simple examples. In this part we will look at some common ways IIFEs are used in applications.
The Module pattern
A common use for IIFEs is to create private members that can only be accessed using public methods. For example, consider the following object literal:
Because all the members of the object literal are public, the count property can be tampered with easily, making this structure less than ideal.
The Module pattern takes advantage of the scope chain by using an IIFE to create a private scope, and then returns an object containing the public methods:
The Revealing Pattern
A variation of the standard Module pattern is called the "Revealing" Module pattern. The difference between the two is that all of the methods are defined in the local IIFE scope, and the returned object contains pointers to the methods to be exposed ('revealed') to the public interface:
Whether you use the standard Module pattern or the Revealing pattern is mostly a matter of style than functionality. YMMV, or course, so where performance is tantamount, always test, test, test.
IIFEs as namespaces
IIFEs can also be used as a namespace strategy. A standard best practice is to avoid cluttering up the global scope with your objects. You can limit what you want exposed in the global scope (or even not have anything in the global scope at all, but I find it useful to at least have one name used, commonly my application singleton) by placing all your private data and functions inside the IIFE, while exposing just the public members you need:
In this example we create an IIFE and pass in our global App object explicitly instead of relying on the scope chain. This helps keep our namespace module stay loosely coupled from any external code. The way we pass the global object into the IIFE may look odd if you're not familiar with the syntax:
Technically, all objects defined in the global scope are in fact members of the window object, so writing:
Is the same as writing:
The other part of the statement is using an 'or' to either use the current App object if it exists (and is not falsy) or an empty object. This is particularly useful if you've broken your code up into several files to make the design more modular. The first namespace module loaded will initialize App as an empty object, while subsequent modules simply extend the existing App.
A good example of this modular namespacing pattern is in developing jQuery plugins. jQuery best practices dictate that a plugin should only use a single name in the jQuery object. Therefore an IIFE is used to privatize the plugin data and methods, with a single public method added to the jQuery object:
Immediately-invoked function expressions are extremely useful for creating privatized data and modularizing our applications. Keep in mind the following:
- Not all IIFEs are closures. If there is no external reference to the objects defined in the IIFE scope then the objects are destroyed once the IIFE finishes executing.
- Passing global objects' (or objects higher up in the scope chain) properties into the IIFE as parameters can increase performance by eliminating internal lookup delays.
- IIFEs are particularly ideal for singleton-type use. If the function is to be reusable, use a named function (assigned or declared) instead.