Data
Data

Reputation: 1357

Why is this function invoked?

Why does this code work? - http://jsfiddle.net/Mq9Ap/1/

$(function() {

    function outer() {
        var counter = 0;
        function inner() {
            alert(counter);
            counter++;
        }
        return inner;
    }

    var x = outer(); // As we're calling outer here, x is a reference to inner 
    x(); // alerts 0
    x(); // alerts 1

});

But it only runs once if i change return inner to return inner()

Edit:

I've confused the intent of my question by mentioning parenthesis. I'm still confused how the inner function is called at all as x() only points to the outer function.

Does the compiler know it should invoke a function if the return value is a pointer to a function?

Upvotes: 0

Views: 60

Answers (4)

Data
Data

Reputation: 1357

I think I've cracked it; my confusion was not so much return inner; but it was:

var x = outer();

I now understand that x holds the return value of outer because of the () invocation which is a function reference to b, so if we now add another () around this returned value, it then invokes that referenced inner function, similar to outer()();

function outer() {
    var counter = 0;
    function inner() {
        console.log(counter);
        counter++;
    }
    return inner;
}

outer()();
outer()();
outer()();

//output
0
0
0

var x = outer(); 
x();
x();
x();

//output
0
1
2

The last section var x works because the outer has been invoked with outer(). When the inner is then called with x(); each time, the counter is already on the stack so the inner function sees it as a static var...i presume.

Confusing stuff this javascript :(

Edit:

Another eureka moment - I realised that outer()(); doesn't work because each time the first outer() is called, it creates a new function context and var counter is initialised each time on the stack and when the second invocation is called, the counter will always be set to zero.

The x = outer(); keeps the counter value from previous function calls, because the function context is saved in x and var counter is only initialised once so it's never reset.

Upvotes: 0

Fizer Khan
Fizer Khan

Reputation: 92865

It is the fact of what you return.

return inner(); actually call the inner function and get the result. That result will be returned. Since inner function does not return anything explicitly, by default it returns undefined. Now x is undefined. You cannot make call on undefined x.

return inner; actually returns reference to inner function. So now x is reference to a function. You can execute x() which will actually invoke inner closure function.

Upvotes: 0

Vivin Paliath
Vivin Paliath

Reputation: 95558

When you do return inner();, you are actually invoking inner and returning the return value , which in this case is undefined since nothing is actually returned. This will then result in an error because undefined is not a function (when you try to call it by doing x()).

When you do return inner;, you are actually returning a reference to the inner function.

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324750

return inner returns the inner function. This can then be called.

return inner() immediately runs the inner function (alerting 0), then returns its return value (undefined). You then get an error that undefined is not a function (when x() tries to call it).

Upvotes: 2

Related Questions