I'm new to Javascript and functional paradigms. I really like using closure to keep little bits of state wrapped up safely in a private scope. It's a refreshing change from the song and dance of class worship in Java.
I wrote the following code with the intention of printing 0-9 to the console. It works, but I'm surprised that it does.
I don't understand how the next
refers to the returned function for the recursive next()
call! Is it related to the "late binding" property of Javascript?
var next = (function() { // begin stateful wrapper function
var current = -1;
return function() { // begin returned function
current += 1;
if (current < 10) {
console.log(current);
next(); // recursive call
} else {
return;
}
}; // end returned function
})(); // immediately call wrapper function
next(); // call returned function to generate output
During execution, how does the recursive next() call already refer to the returned function?
Where can one read about the details of what's going on here?
(Output:)
0
1
2
3
4
5
6
7
8
9
Perhaps you're confused by the outermost function that is being invoked immediately. This serves only to protect current
in a variable scope. If we eliminate that, it's probably clearer.
var current = -1;
var next = function() {// This is what would have been returned in the original
current += 1;
if (current < 10) {
console.log(current);
next(); // recursive call
} else {
return;
}
};
next();
Now you have the same as the original code, except that current
isn't in its own scope. As you can see, the function is simply assigned to the next
variable.
That's exactly what's happening in the original, except that in the original the outer function exists and is immediately invoked. That outer function is a one-time-shot function, and is not assigned to next
, though its return
value is.
JavaScript doesn't have block scope (yet), but if it did, think of it as being similar to this:
var next;
{ // Create a (fictional) variable scope that has `current` and the function
var current = -1;
next = function() {
current += 1;
if (current < 10) {
console.log(current);
next(); // recursive call
} else {
return;
}
};
}
next();
But since JS doesn't have block scope, but only function scope, we need to emulate this with a function.
We can tweak the original just a little to make it look similar.
var next;
(function() { // Create a variable scope that has `current` and the function
var current = -1;
next = function() {
current += 1;
if (current < 10) {
console.log(current);
next(); // recursive call
} else {
return;
}
};
}());
next();