Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion regarding javascript closure

While developer a client side application I ran into an error that I believe is related to my incomplete understanding of use of closures. I have trimmed down my code to the following :


var fn1 = function(arr){ 
  return function(val){ 
    var idx;
    var x = 20; 
    for (idx in arr) {
      arr[idx]();
    } 
  } 
}

var fn2 = fn1([function(){
  x+= 20; 
  alert(x);
}])

Now upon executing :

fn2()

I receive an error : ReferenceError: reference to undefined property "x"

I would like to know why this error is arising and why can't fn2 access the variables defined in the local scope of closure function returned by fn1 ?

like image 719
lorefnon Avatar asked Dec 20 '22 20:12

lorefnon


1 Answers

In short: closures have access to parent scopes in relation to where they were declared, not where they are used.

The function returned by fn1 has access to the scope of its parent function (fn1 itself), i.e., it has access to arr. But the functions inside your array do not have access to variables defined within fn1 or within the function returned from it, because those functions (inside array) were declared in a different scope.

Regarding the actual problem you're trying to solve with that code, I'm not sure if I understood it correctly. Looks like you're trying to apply some functions to a certain number. I don't understand why that number (20 in your example) is a constant and not a parameter. Here is my proposed solution for that (no closures!):

var applyArrayFunctions = function(arr, x){ 
    for(var i=0; i<arr.length; i++) {
        x = arr[i](x);
    }
    return x;
}

var num = 2;
var fnArray = [
    function(val){
      return val + 20; 
    },
    function(val){
      return val * 2; 
    }
];

console.log(applyArrayFunctions(fnArray, num));​ // logs 44​​​
like image 108
bfavaretto Avatar answered Dec 23 '22 09:12

bfavaretto