views:

48

answers:

1

I'd just like to check my understanding of variable copying in Javascript. From what I gather, variables are passed/assigned by reference unless you explicitly tell them to create a copy with the new operator. But I'm a little uncertain when it comes to using closures. Say I have the following code:

var myArray = [1, 5, 10, 15, 20];
var fnlist = [];
for (var i in myArray) {
    var data = myArray[i];
    fnlist.push(function() {
        var x = data;
        console.log(x);
    });
}
fnlist[2](); // returns 20

I gather that this is because fnlist[2] only looks up the value of data at the point where it is invoked. So I tried an alternative tack:

var myArray = [1, 5, 10, 15, 20];
var fnlist = [];
for (var i in myArray) {
    var data = myArray[i];
    fnlist.push(function() {
        var x = data;
        return function() {
            console.log(x);         
        }
    }());
}
fnlist[2](); // returns 10

So now it returns the 'correct' value. Am I right to say that it works because a function resolves all variable references to their 'constant' values when it is invoked? Or is there a better way to explain it?

Any explanations / links to explanations regarding this referencing / copying business would be appreciated as well. Thanks!

+1  A: 

Closure variables are bound ("saved" in the closure) at the moment when its scope ends, that is, when you leave the function where the closure is defined:

function make_closure() {
   var x = 10;
   var closure = function() { alert(x) }
   x = 20
   return closure;
}

func = make_closure()
func() // what do you think?

The solution you've found is perfectly correct - you introduce yet another scope and force closure to bind variables in that "inner" scope.

See here for details and explanations.

stereofrog
That's not really accurate. There's no real "saving" going on, and no copying. that function created inside "make_closure" were to be called before the statement that sets "x" to 20, it's show "10" in the alert.
Pointy