I'm sure there's a really simple solution to this but I can't wrap my head around it. I'm trying to create and array of objects within a for loop like so:
for(var i = 0; i < 100; i++) {
foos[i] = new Foo(i*10);
bars[i] = someObject.createBar({
x : 0,
y : 0,
foobar = function() {
foo[i].a = true;
}
});
}
When trying to run this I get 'cannot set property a of undefined', both foos and bars are declared earlier in the code as globals.
It works fine if I create foos as foos[0] and access through bars[0]. I suspect it's something to do with function level scoping but as far as i can see the arrays should be accessible on the global object....
4 Answers 4
You need to "anchor" the value of i. To do this...
for(var i=0; i<100; i++) {
(function(i) {
// now do stuff with i
})(i);
}
Comments
Try this:
for(var i = 0; i < 100; i++) {
foos.push( new Foo(i*10) );
bars.push( someObject.createBar({
x : 0,
y : 0,
foobar = function() {
foo[i].a = true;
}
}) );
}
You cannot set value "a" of undefined, because "foo[i]" is undefined. You never defined foo[i]. Did you mean foos[i], maybe?
Also, as others have said, your function foobar is going to use the same value of i for every object you create. You should create a new closure with i, which will allow you to define a local variable i that can be different for each interior function, as so:
for(var i=0; i<100; i++) {
(function(i) {
// now do stuff with i
})(i);
}
Comments
The value of i in the execution of foobar is the one at the end of your loop (100). Because the loop block is a closure.
You'd better store the value you want. For example :
for(var i = 0; i < 100; i++) {
foos[i] = new Foo(i*10);
bars[i] = someObject.createBar({
x : 0,
y : 0,
i : i,
foobar: function() {
foos[i].a = true;
}
});
}
Or use a intermediate closure in your loop to enclose i :
for(var i = 0; i < 100; i++) {
(function(i){
foos[i] = new Foo(i*10);
bars[i] = someObject.createBar({
x : 0,
y : 0,
foobar: function() {
foos[i].a = true;
}
});
})(i);
}
The first solution is more explicit, the second one is maybe now more usual.
foobar =can't be used withing object literal notation