# Solving the puzzle in javascript

I've recently try to brush up my javascript skills, so I have a friend who gives me puzzles from time to time to solve. Yesterday I got this :

function testFun() {
f = {};
for( var i=0 ; i<3 : i++ ) {
f[i] = function() { alert("sum='+i+f.length); }
}
return f;
}

Expected Results:
testFun()[0]() should alert “sum=0”
testFun()[1]() should alert “sum=2”
testFun()[2]() should alert “sum=4”


I did this which does like requested above:

function testFun() {
var i,
f = {};
for (i = 0; i < 3; i++) {
f[i] = (function(number) {
return function() {
alert("sum=" + (number * 2));
}
}(i));
}
return f;
}


Could my answer be written better and what can be improved if so?

• @Malachi, thank you for the link, will keep it in mind. Nov 8, 2013 at 17:57
• @AlexAtNet, BTW, it is on the top of the page along with the ABOUT page
– Malachi
Nov 8, 2013 at 17:58
• ok I edited my question to fit the rules, thanks for your comments Nov 8, 2013 at 17:58
• it's all good, it is hard to see <voicetone> tags on the internet. so I read everything in a pleasant and helpful tone so that if I do take it the wrong way I still don't take offense.
– Malachi
Nov 8, 2013 at 18:05

The style of you code is good. Here is not much of it but it looks like you understand the concept of closures well.

The logic of the original task is changed so even if you code returns the right values, they are calculated differently. The original task calculates it as i + f.length. It is questionable how to calculate length of an object. There are some ways but we can simply guess that the initialization of f is incorrect and f should be an array.

Another question is how to capture the current state of the array in the closure. Because it is object the closure will get the reference to it so it should be copied. The simplest way of copying an array it to call f.slice().

The last issue (reported by jshint) is that the function created in the loop is always the same. So you can move it outside of the loop and just call in the loop.

Update: Some notes on capturing objects in closures.

The closure captures variable by reference. If you have a loop with an index variable and capture this variable and then invoke the closure you will have not the value of the variable on the corresponding loop iteration. What you will get is the final value on the last loop iteration.

To capture the value the variable should be copied to some temporary context. In the languages with statement scope it is enough to declare local variable, but in JS with function scope you need to capture the variable by running the function. That is why in your code you have this function(number) { - it copies the index variable i to the function parameter number and when value of i is changed, value of number remains.

But when you capturing objects the situation is different, because objects are passed into function scope by reference too. So if the state of the object is changed, it will be changed in both parent and function scope. So in your example later, while invoking, the function will add the final length of the array to the variable, not the length of the array from the corresponding loop iteration.

So the length somehow should be preserved in the closure. It can be passed as number but it will be too boring - you already know how to deal with them. So it is better to think how to pass the copy of the array itself.

    f[i] = (function(number, array) {
return function() {
alert("sum=" + number + array.length);
}
}(i, f.slice()));

• Thanks for the comments that was really useful, I changed f to be an array and put the function outside the for loop. Could you further explain the capturing array in the closure? what you mean by that. thanks Nov 8, 2013 at 18:45
• I've added the nodes on objects. Nov 8, 2013 at 19:32