Search code examples
javascriptfunctionrecursionclosureslate-binding

Javascript closure returning a recursive function


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

Solution

  • 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();