Immediately Invoked Function Expression

You might also like

You are on page 1of 4

Immediately invoked function

expression
From Wikipedia, the free encyclopedia
Jump to navigationJump to search
An immediately invoked function expression (or IIFE, pronounced "iffy")[1] is
a JavaScript programming language idiom which produces a lexical scope using
JavaScript's function scoping.
Immediately invoked function expressions can be used to avoid variable
hoisting from within blocks, protect against polluting the global environment and
simultaneously allow public access to methods while retaining privacy for
variables defined within the function.

Contents

1Usage
2Examples
o 2.1Evaluation context
o 2.2Establishing private variables and accessors
3Terminology
4See also
5References
6External links

Usage[edit]
Immediately invoked function expressions may be written in a number of different
ways.[2] A common convention is to enclose the function expression – and
optionally its invocation operator – with the grouping operator,[3] in parentheses, to
tell the parser explicitly to expect an expression. Otherwise, in most situations,
when the parser encounters the function keyword, it treats it as a function
declaration (statement), and not as a function expression.[4][5]

(function () { /* ... */ })();


(function () { /* ... */ }());
(() => { /* ... */ })(); // With ES6 arrow functions
(though parentheses only allowed on outside)

There are other ways to enforce a function expression:

!function () { /* ... */ }();


~function () { /* ... */ }();
-function () { /* ... */ }();
+function () { /* ... */ }();
void function () { /* ... */ }();

In contexts where an expression is expected, wrapping in parentheses is not


necessary:

var f = function () { /* ... */ }();


true && function () { /* ... */ }();
0, function () { /* ... */ }();

Passing variables into the scope is done as follows:

(function(a, b) { /* ... */ })("hello", "world");

An initial parenthesis is one case where the automatic semicolon insertion (ASI)
in JavaScript can cause problems; the expression is instead interpreted as a call
to the last term on the preceding line. In some styles that omit optional
semicolons, the semicolon is placed in front of the parenthesis, and is known as
a defensive semicolon.[6][7] For example:

a = b + c
;(function () {
// code
})();

...to avoid being parsed as c() .

Examples[edit]
The key to understanding design patterns such as IIFE is to realize that until
recently[when?] JavaScript only featured function scope (thus lacking block scope),
passing values by reference inside closures.[8] This is no longer the case, as the
ES6 version of JavaScript implements block scoping using the
new let and const keywords.[9]

Evaluation context[edit]
A lack of block scope means that variables defined inside (for example) a for
loop will have their definition "hoisted" to the top of the enclosing function.
Evaluating a function that depends on variables modified by the outer function
(including by iteration) can be difficult. We can see this without a loop if we
update a value between defining and invoking the function.[10]

var v, getValue;
v = 1;
getValue = function () { return v; };
v = 2;

getValue(); // 2

While the result may seem obvious when updating v manually, it can produce
unintended results when getValue() is defined inside a loop.

Hereafter the function passes v as an argument and is invoked immediately,


preserving the inner function's execution context.[11]

var v, getValue;
v = 1;
getValue = (function (x) {
return function () { return x; };
})(v);
v = 2;

getValue(); // 1

This is equivalent to the following code:

var v, getValue;
v = 1;
function f(x) {
return function () { return x; };
};
getValue = f(v);
v = 2;

getValue(); // 1

David Herman's Effective JavaScript contains an example illustrating the


problems of evaluation context inside loops.[12] While Herman's example is
deliberately convoluted, it arises directly from the same lack of block scope. [13]
Establishing private variables and accessors[edit]
IIFEs are also useful for establishing private methods for accessible functions
while still exposing some properties for later use.[14] The following example comes
from Alman's post on IIFEs.[1]
// "counter" is a function that returns an object
with properties, which in this case are functions.
var counter = (function () {
var i = 0;

return {
get: function () {
return i;
},
set: function (val) {
i = val;
},
increment: function () {
return ++i;
}
};
})();

// These calls access the function properties


returned by "counter".
counter.get(); // 0
counter.set(3);
counter.increment(); // 4
counter.increment(); // 5

If we attempt to access counter.i from the global environment, it will be


undefined, as it is enclosed within the invoked function and is not a property
of counter . Likewise, if we attempt to access i , it will result in an error, as we
have not declared i in the global environment.

Terminology[edit]
Originally known as a "self-executing anonymous function",[15] Ben Alman later
introduced the current term IIFE as a more semantically accurate name for the
idiom, shortly after its discussion arose on comp.lang.javascript.[1][16][17]
Notably, immediately invoked functions need not be anonymous inherently,
and ECMAScript 5's strict mode forbids arguments.callee ,[18] rendering the
original term a misnomer.

You might also like