function
loopBody
(
i
) {
setTimeout
(
function
() {
console
.
log
(
i
===
0
?
"go!"
:
i
);
}, (
5
-
i
)
*
1000
);
}
var
i
;
for
(
i
=
5
;
i
>
0
;
i
--
) {
loopBody
(
i
);
}
At each step in the loop, the function
loopBody
is invoked. Recall how arguments are
passed in JavaScript: by value. So at each step, it’s not the variable
i
that gets passed
into the function, but the value of
i
. So the first time, the value
5
is passed in, the
second time the value
4
, and so on. It doesn’t matter that we use the same variable
name (
i
) in both places: we’re essentially creating six different scopes and six inde‐
pendent variables (one for the outer scope, and five for each of the
loopBody
invoca‐
tions).
Creating a named function for loops that you are only going to use once can get tedi‐
ous, though. Enter IIFEs: they essentially create equivalent anonymous functions that
are invoked immediately. Here’s how the previous example looks with an IIFE:
var
i
;
for
(
i
=
5
;
i
>
0
;
i
--
) {
(
function
(
i
) {
setTimeout
(
function
() {
console
.
log
(
i
===
0
?
"go!"
:
i
);
}, (
5
-
i
)
*
1000
);
})(
i
);
}
That’s a lot of parentheses! If you think about it, though, the exact same thing is being
accomplished: we’re creating a function that takes a single argument, and invokes it
for each step in the loop (see
for a visual explanation).
Figure 13-1. Immediately invoked function expression
190 | Chapter 13: Functions and the Power of Abstract Thinking