2

Both of these examples of closures have the benefit of preserving the value of count in subsequent function calls, whereas otherwise (if a closure were not used), count would reset to 0 following each function invocation. Further, in both cases the count variable (as any let variable in a block) is private, that is, not globally accessible.

The IFFE closure example was adapted from Marius Schulz' article, in which he suggested that usage. The only advantage of using the IFFE version of the closure over the regular version that I can think of is that you don't have to name it (you just have to assign it to a variable in order to call it again)—or if you do name it, it won't be visible in the global scope—so there's one fewer item polluting the global namespace. Is there some other benefit I'm overlooking?

Regular closure:

function createCounter() {
  let count = 0;
  return function() {
    ++count;
    return `count equals ${count}`;
  };
};

let counter = createCounter();

console.log(counter()); // count equals 1 
console.log(counter()); // count equals 2

IFFE closure:

let countingFunction = (function() {
  let count = 0;
  return function() {
    ++count;
    return `count equals ${count}`;
  };
})();

console.log(countingFunction()); // count equals 1
console.log(countingFunction()); // count equals 2

Edit: The question marked as a duplicate is a different question, and the chosen answer doesn't answer this question.

nCardot
  • 5,992
  • 6
  • 47
  • 83
  • Possible duplicate of [How does an IIFE's being called immediately prevent it from polluting global scope?](https://stackoverflow.com/questions/50940766/how-does-an-iifes-being-called-immediately-prevent-it-from-polluting-global-sco) – Patrick Roberts Jun 22 '18 at 02:54
  • 1
    Patrick, I asked that question yesterday. It is not asking the same thing (and the chosen answer doesn't answer this question). – nCardot Jun 22 '18 at 02:59

1 Answers1

5

The difference is that the IIFE closure can only be used once, whereas the first one can be called to make a new iterator whenever desired, kind of like a generator.

For example, if you have one queue of sorts you want to iterate through on demand, you might use the second IIFE version, but if you have two queues, you might call countingFunction twice in order to create separate counter.

If you only ever need one such counter, though, you can wrap it an IIFE to make it clear that it's going to be used once, and only once, and to avoid creating a variable that isn't going to be used again. (This is useful not so much for script optimization, but for readability)

Side note - it would probably be a bit clearer to name the variables more consistently, since the first countingFunction is quite different from the second countingFunction. The first one, when called, creates something that counts, the second one is something that counts. Perhaps call the first one makeCounter and the second one counter:

Regular closure:

function makeCounter() {
  let count = 0;
  return function() {
    ++count;
    return `count equals ${count}`;
  };
};

let counter = makeCounter();

console.log(counter()); // count equals 1 
console.log(counter()); // count equals 2

IFFE closure:

let counter = (function() {
  let count = 0;
  return function() {
    ++count;
    return `count equals ${count}`;
  };
})();

console.log(counter()); // count equals 1
console.log(counter()); // count equals 2
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320