Nice article, thanks. I agree with your premise that we shouldn’t be using IIFEs unnecessarily.
I just want to point out that sometimes using IIFEs for closures can be beneficial. However those are fairly rare cases, so I still agree when you say “We don’t need IIFEs for closures as much anymore”. You don’t seem to be saying that we should never use IIFEs for closures.
A simple example is when using the facade pattern. It would also be helpful to not pollute the module with the real function. For example, when using recursion with tail call optimisation:
const sumRange = n => {
const _sumRange = (n, current = 0) => {
if (n <= 0) return current;
return _sumRange(n - 1, current + n);
};
return _sumRange(n);
};
_sumRange
is essentially an IIFE. I’ve just separated the call into a different line for readability.
This is optional, and we could structure the code otherwise, but in my opinion it’s a bit cleaner than having the sumRange
function in the module (especially if we have multiple other functions in there) or giving the user the option to use it when they shouldn’t do.
(As a final note, yes JavaScript doesn’t have tail call optimisation, but the exact same principle applies with the “trampolining” technique. That’s more complicated, so I used tail-call optimisation instead.)