Aegis
Aegis

Reputation: 101

JS closures and recursion

For example I have this function with a closure:

function getData() {
    var status = 0;

    var func = function() {
        status++
        alert(status);
    }

    return func;
}

Its works correctly and the variable "status" is visible within the closure function.

But if I transfer the closure code into the separate function the closure variable "status" isn't available:

function getData() {
    var status = 0;

    var func = function() {
        myFunction();
    }

    return func;
}


function myFunction() {
     status++
     alert(status);
}

Yes, I can send this variable to the function and then return the changed value. But what if I need recursion in "myFunction"?

function getData() {
    var status = 0;

    var a = function() {
        myFunction(status);
    }
    return a;
}


function myFunction(status) {

     if (status == 0) {
          status = 1;
          // After calling this function again "status" will reset to 0, 
          // but I want to save current value (status = 1). 
          data();
     }
     return status++;

}

var data = getData();
data();

How can I get one instance of my variable "status" for all calls to the closure function.

Thanks!

Upvotes: 2

Views: 311

Answers (3)

Bergi
Bergi

Reputation: 664650

If I transfer the closure code into the separate function the closure variable "status" isn't available.

True, and that won't change due to JavaScript's scoping rules.

Yes, I can send this variable to the function and then return the changed value. But what if I need recursion in "myFunction"?

Nothing changes. You can use recursion from inside the closure as well.

function getData() {
    var status = 0;

    function data() {
        if (status++ == 0) {
            // do anything you want
            // including recursive calls to `data()`
        }
        return status;
    }

    return data;
}

getData()();

Upvotes: 0

sanchez
sanchez

Reputation: 4530

You could replace this line:

myFunction(status);

with:

status = myFunction(status);

or:

JSFIDDLE: http://jsfiddle.net/KHZRr/

function Data(){

    var status = 0;

    var a = {
        getData : function(){
            if( status == 0 ){
                status = 1;
                return "FIRST, status = " + status;
            }else{
                return "NOT FIRST, status = " + status;
            }
        }
    }
    return a;
}



var data = Data();
alert( data.getData() );
alert( data.getData() );
alert( data.getData() );

Is this what you are looking for?

Upvotes: 1

Dogbert
Dogbert

Reputation: 222198

Firstly, that doesn't work because JS has lexical scopes, not dynamic scopes. More info on Wikipedia

Secondly, if you want to pass in a variable to a function, and allow that function to mutate it, you need to send something that's an instanceof Object.

0 instanceof Object
false
"" instanceof Object
false
[] instanceof Object
true
({}) instanceof Object
true
(function(){}) instanceof Object
true

You can wrap your number into an object and pass it.

Modified example:

function getData() {
    var o = {
        status: 0
    };

    var a = function () {
        myFunction(o);
    }
    return a;
}


function myFunction(o) {
    console.log(o);
    if (o.status == 0) {
        o.status = 1;
        // After calling this function again "status" will reset to 0, 
        // but I want to save current value (status = 1). 
        data();
    }
    return o.status++;
}

var data = getData();
data();

Output:

Object {status: 0}
Object {status: 1}

http://jsfiddle.net/Dogbert/Tw7nh/

Upvotes: 2

Related Questions