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:

  1. an enclosing lexical scope within its grouping
  2. 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

Refs

1, 2