0

The code below generates this error:

Uncaught TypeError: Cannot read property '5' of undefined

This is thrown by line 52 of the code below. I don't understand how the value of rows or cols gets to 5, when the two loops are set to stop at 4.

Thanks for any help.

//globals define 
define(function(require, exports, module) {
    'use strict';
    // import dependencies
    var Engine = require('famous/core/Engine');
    var Surface = require('famous/core/Surface')
    var Modifier = require('famous/core/Modifier');
    var PhysicsEngine = require('famous/physics/PhysicsEngine');
    var Particle = require('famous/physics/bodies/Particle');
    var Drag = require('famous/physics/forces/Drag');
    var RepulsionForce = require('famous/physics/forces/Repulsion')

    var positionsArray = [-140,-70,0,70,140];

    var context = Engine.createContext();

    var physics = new PhysicsEngine();

    var planetParticle = new Particle({
        position:[0,0,0]
    });

    physics.addBody(planetParticle);

    var gridItem = [];
    var gridItemParticle = [];
    var gridItemModifier = [];


    for (var rows = 0; rows < 5; rows += 1){
        gridItem[rows] = [];
        gridItemParticle[rows] = [];
        gridItemModifier[rows] = [];
        for (var cols = 0; cols < 5; cols += 1){
           gridItem [rows][cols] = new Surface({
            properties: {
                backgroundColor: '#23AD23'
            }
            }); 

           gridItemParticle[rows][cols] = new Particle({
            position: [positionsArray[rows], positionsArray[cols], 0]
           });

           physics.addBody(gridItemParticle[rows][cols]);

           gridItemModifier[rows][cols] = new Modifier({
            size: [50,50],
            align: [0.5, 0.5],
            origin: [0.5, 0.5],

            //---------------------This is the line that throws the error
            transform: function() {
             return gridItemParticle[rows][cols].getTransform();
            }
           });

           context.add(gridItemModifier[rows][cols]).add(gridItem[rows][cols]);
        }
    }

});
Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
Timbo
  • 125
  • 8

2 Answers2

0

The transform function is created, but not executed at this stage.

By the time the transform function is called, the counters are indeed 5, which is why the loop exited.

Example:

rows = 0 - Loops (adds a transform function)
rows = 1 - Loops (adds a transform function)
rows = 2 - Loops (adds a transform function)
rows = 3 - Loops (adds a transform function)
rows = 4 - Loops (adds a transform function)
rows = 5 - Exits loop...

If you call one of those functions now, the value of rows is 5.

Here is a short example of the problem:

var functionList = [];

for (var i = 0; i < 5; i++) {
    functionList.push(function () {
        alert(i);
    });
}

functionList[0]();
Fenton
  • 241,084
  • 71
  • 387
  • 401
0

This is not really a Famo.us Physics issue. It is an issue with how you are trying to bind a call to your function. Best practices are to not create anonymous functions in your loops.

The values of rows and cols need to be bound to your function for later use.

        //---------------------This is the line that throws the error
        transform: function() {
         return gridItemParticle[rows][cols].getTransform();
        }

could be changed to

        //--------------------- bind your values
        transform: gridItemTrans.bind({row: rows, col: cols})

create a function outside your loop

        function gridItemTrans() {
            return gridItemParticle[this.row][this.col].getTransform();
        }
talves
  • 13,993
  • 5
  • 40
  • 63
  • Thanks heaps for your help; all works now. If I understand the principle correctly, passing the values of the loop counters out as arguments to a separate function preserves them as they are enclosed in that function's scope, whereas the loop's variables are in the global scope. – Timbo Apr 30 '15 at 10:41
  • Yes each variable declaration is not local to the loop like in other languages but have the same scope as the loop itself. This is why you must bind that value to the call of the function, because the value of the variable changes on each iteration. Hence the reason every call was using the last value of the variables. – talves Apr 30 '15 at 14:31