dz210
dz210

Reputation: 768

JavaScript give called function access to calling function variables

If I define an inner function inside a function, the inner function has access to the outer function's variables. If I want this inner function to be reusable and define it outside the outer function, the inner function now loses access to the outer function variables. How do I make this new reusable inner function have access to outside function variables, without passing those variables in as parameters?

        function a () {

        var x = [[1,2,3], [1,2,3], [1,2,3]];

        var keys = Object.keys(x[0]);

        for (var i = 0; i < x.length; i++) {
            angular.forEach(keys, loop);
        }

        }

        function loop (key) {
            console.log(key, i);//i is undefined here
        }
        a();

Specifically, is there some way without 1) assigning variables to this, 2) without passing in variables as parameters, and 3) without creating global variables?

Edit: It seems there is no way to do this. But if I try another approach, to have the reusable function return a new function, I also do not have access to the inner scope. Why is this, and is there some way to make this work?

        function a () {

        var x = [[1,2,3], [1,2,3], [1,2,3]];

        var keys = Object.keys(x[0]);
        var myloop = loop();

        for (var i = 0; i < x.length; i++) {
            angular.forEach(keys, myloop);
        }

        }

        function loop (key) {
            return function(key) {
                 console.log(key, i);//i is undefined here
            };
        }
        a();

Upvotes: 3

Views: 1200

Answers (5)

dz210
dz210

Reputation: 768

I also want to make another option known which I just discovered. If you use .bind, you can curry the function with i, and the other variables will be passed in after the curried parameters.

 ....
 angular.forEach(keys, loop.bind(null, i));
 ...

 function loop(i, key) {
 ...
 }

Upvotes: 1

Adeel Zafar Soomro
Adeel Zafar Soomro

Reputation: 1522

In the following example, loop returns a function that closes over the value of i.

function a () {
    var x = [[1,2,3], [1,2,3], [1,2,3]];

    var keys = Object.keys(x[0]);

    for (var i = 0; i < keys.length; i++) {
        keys.forEach(loop(i));
    }
}

function loop (i) {
    return function (key) {
        console.log(key, i);  // i is now defined
    }
}

a();

Output:

0 0
1 0
2 0
0 1
1 1
2 1
0 2
1 2
2 2

Upvotes: 2

Felix Kling
Felix Kling

Reputation: 816462

How do I make this new reusable inner function have access to outside function variables, without passing those variables in as parameters?

You can't. JavaScript has lexical scope, not dynamic scope.

See also: What is lexical scope?

Upvotes: 1

bitrecycling
bitrecycling

Reputation: 55

In JS (and many other languages), there is a visibility context. Possible contexts are e.g. "global" or function or block. These contexts are hierarchical, inner can read outer. Outer can never read inner (encapsulation principle) unless inner declares variable as global.

Upvotes: 0

Adarsha
Adarsha

Reputation: 21

Inner functions are treated locally by the outer function. Therefore, you can access the variables belonging to the outer function from the inner function. But, once you have the inner function as a separate function outside the outer function, then you no longer have access to the private data variables of the outer function.

If this seems complicated, here is an example:

function A
{
  //variables
  function B
  {
   can use variables of A
  }
}

But,

    function A
    {
      //variables
    }
    function B
    {
     //cannot access variables of A
    }

Upvotes: 0

Related Questions