Hint
IIFE was the pre-let solution: capture the current value as a function argument to create a new binding.
const fns = [];
for (var i = 0; i < 3; i++) {
fns.push((function(j) {
return () => j;
})(i));
}
console.log(fns[0]());
console.log(fns[2]());0 2
Explanation: The IIFE captures i as parameter j at call time. j is a fresh binding per IIFE invocation — not shared like var i.
Key Insight: IIFE was the pre-let solution: capture the current value as a function argument to create a new binding.