1

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
  • 3
    Is this just because you're trying to set foo[i].a rather than foos[i].a in the foobar function? Commented Jun 18, 2012 at 19:12
  • @dougajmcdonald Well seen. We all immediatly think about a closure problem but it may be just a typo... Commented Jun 18, 2012 at 19:16
  • 2
    Your syntax is invalid. foobar = can't be used withing object literal notation Commented Jun 18, 2012 at 19:27
  • two typos there then! - it was the closure problem Commented Jun 18, 2012 at 19:29

4 Answers 4

3

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);
}
Sign up to request clarification or add additional context in comments.

Comments

0

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; 
         } 
    }) ); 
} 

1 Comment

It's a scope issue within the foobar handler. Using .push won't help here.
0

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

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.