Notes on Javascript closures and Immediately Invoked Function Expression (IIFE)
In this article the question was posed, as an example of what may be asked of an applicant for a software developer job, to explain what was happening here:
const getUid = (() => {
let uid = 0;
return () => ++uid;
})();
console.log(getUid());
console.log(getUid());
The key concepts involved are
- variable scope,
- IIFE (immediately invoked function expression), and
- closure.
An IIFE has this format:
const func = (() => {
// statements
})();
The constant (variable) getUid
is allocated to a function which is also immediately invoked,
hence its descriptive name. An IIFE is a design pattern
which has two important features, namely:
- an enclosing lexical scope within its grouping
- it is immediately invoked by the Javascript engine.
In practical terms, and in this example, on creation, within the function the variable uid
is
initialised with the value 0
but importantly is ONLY available within the lexical scope of the
function. The function itself then returns an anonymous “inner” function which has access to and
tracks any variables defined within its enclosing scope - a key characteristic of Javascript -
and here this inner anonymous function has access to the variable uid
. Actually it stores a
reference to the outer variable. Such an inner function is referred to a closure
. Through the
returned closure
function, the stored variable uid
is both incremented and then exposed when
the outer function, or more correctly a reference to the function, is called.
The following is an example derived from the Wikipedia page on IIFE which returns an object whose keys point to closure functions which expose the inner variable:
const counter = (() => {
let i = 0;
return {
get: () => i,
set: (val) => i = val,
increment: () => ++i,
}
})();
Then calling and accessing the function properties returned by counter
:
> counter.get()
0
> counter.set(99)
99
> counter.increment()
100