1

This is an academic question concerning javascript.

The code segment below takes an array of integers, and returns an array of pointers to functions. The functions pointed to are suppose to return the squared value of the array.

If the input was listOfFunction = sqFnList([1,2,3,4,5])

Then listOfFunction[0]() should return 1

and listOfFunction[1]() should return 4

but it does not.

function sqFnList(a){
   var b = [];
   for ( var i = 0; i <a.length; i++)
   {
      var sq = a[i] * a[i];
      b[i] = function() { return sq;}
   }
   return b;
}

 x = sqFnList([3,4,5])[0]()

The issues is that x = 25. Thanks for the help in advance.

techfoobar
  • 65,616
  • 14
  • 114
  • 135
John b
  • 1,338
  • 8
  • 16
  • Since all objects are only references in JS, we usually don't talk of "pointers". It's just an "array of functions" – Bergi May 28 '13 at 17:24
  • That is neat, thanks for the heads up. Thank every one who help me out. – John b May 28 '13 at 17:29

2 Answers2

4

Your functions all contain a reference to the same variable sq, which has the value 25 once you actually call the functions. You need to create a separate closure for each function, each with its own copy of sq's value, in order to capture the value of sq at the time you want:

function sqFnList(a){
   var b = [];
   for ( var i = 0; i <a.length; i++)
   {
      var sq = a[i] * a[i];
       b[i] = function (the_sq) {
          return function() { return the_sq;}
       }(sq);
   }
   return b;
}

x = sqFnList([3,4,5])[0]()  // x is 9

Here's a fiddle to demonstrate.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
RichieHindle
  • 272,464
  • 47
  • 358
  • 399
2

sq is scoped to sqFnList and you keep updating the value, changing it in all the closures. You need to force a new scope for sq:

function sqFnList(a){
   var b = [];
   for ( var i = 0; i <a.length; i++)
   {
      var sq = a[i] * a[i];
      (function(sq) {
        b[i] = function() { return sq;}
      })(sq);
   }
   return b;
}
Dark Falcon
  • 43,592
  • 5
  • 83
  • 98