user1406186
user1406186

Reputation: 1002

Uncaught TypeError: Cannot set property '0' of undefined "

i'm getting the error

Uncaught TypeError: Cannot set property '0' of undefined

for some reason in this line

world_map_array[i][z]="grass.gif|ongrass.gif|collision.gif|above.gif";

Why is this happening?

thanks for any help

var x_world_map_tiles = 100; 
var y_world_map_tiles = 100; 

var world_map_array = new Array(x_world_map_tiles);
for (i=0; i<=2; i++)//create a two dimensional array so can access the map through x and y coords map_array[0][1] etc.
{
world_map_array[i]=new Array(y_world_map_tiles);
}


for (i=0; i<=x_world_map_tiles; i++)//just a test
{
for (z=0; z<=y_world_map_tiles; z++)//just a test
{
world_map_array[i][z]="grass.gif|ongrass.gif|collision.gif|above.gif";
}
}

Upvotes: 22

Views: 96012

Answers (5)

user9205263
user9205263

Reputation: 1

Getting Uncaught TypeError while using 2-D array in javascript.

For two- dimension array, first declare parent array

var arryTwoDimension= [];

Then depending on the situation, we can create child array by

arryTwoDimension[i]=[] i will be from 0,1,2......

This will solve the issue.

Upvotes: -1

Matt McMahon
Matt McMahon

Reputation: 655

Arrays in JavaScript have quirks of their own that you may not be expecting if you come from other languages. Two important ones for your use case are:

  1. You cannot directly declare multidimension arrays in JavaScript.
  2. There's little efficiency benefit (and no added safety) when you set the size of the array at creation.

Unlike other languages, JavaScript won't allocate a block of memory for the full array. (It doesn't know what kind of objects you're going to be putting in each cell, and therefore how much total memory it will need.) Instead, all the size argument to Array() does for you is set the array's length property.

For the general, 2d array case, I'd suggest:

  1. Create the "top" array, e.g.:

    var i       // the first-order index in a
      , j       // the second order index in a
      , a = []
    
  2. Initialize array elements as needed. This is called lazy initialization, and, in this case, it simply involves testing that a[i] exists before we try to assign something to a[i][j], e.g.:

    if (!a[i]) a[i] = []
    

    In English the above statement reads: "If the i-th element of a is 'falsy', assign an empty array to the i-th element."

  3. Finally, assign the actual value to the multideminsional array:

    a[i][j] = 'whatever'
    

For your case, you know the values ahead of time, so you can initialize each element in advance. (If you're not overriding most of the elements, however, a lazy implementation may be better; see below.)

var x, x_length = 100
  , y, y_length = 100
  , map = []

// Don't be lazy
for (x = 0; x < x_length; x++) {
  map[x] = []
  for (y = 0; y < y_length; y++) {
    map[x][y] = 'grass.gif|ongrass.gif|collision.gif|above.gif'
  }
}

As some others have said, an array with 100 elements has indexes numbered from zero to ninety-nine, so a less-than comparison is most appropriate here.


For reference, here's an implementation that uses lazy initialization. I've gone with a function interface instead of directly accessing the array; it's longer and more complex, but also more complete.

The initialization pattern I've used here is called an immediately invoked function expression. If you haven't seen it before, it's one of the more useful JavaScript patterns and well worth taking some time to understand.

var map = (function (x_length, y_length, v_default, undefined) {
  // Unless v_default is overwritten, use ...
  v_default = v_default || 'grass.gif|ongrass.gif|collision.gif|above.gif'

  // Private backing array; will contain only values for a[x][y] 
  // that were explicitly set.
  var a = []

  // Private helper function. 
  // - Returns `true` if `x` is between `0` and `x_length - 1`
  //   and `y` is between `0` and `y_length - 1`.
  // - Returns `false` otherwise.
  function valid (x, y) {
    return (x >= 0 
      &&    x <  x_length
      &&    y >= 0
      &&    y <  y_length)
  }

  // Private helper function.
  // - Returns `true` if a[x][y] has been set().
  // - Returns `false` otherwise.
  function exists (x, y) {
    return !!a[x] && !!a[x][y]
  }

  // Private getter
  // - Returns the value of a[x][y] if it has been set().
  // - Returns `undefined` if the point (x,y) is invalid.
  // - Returns `v_default` otherwise.
  function get (x, y) {
    if (!valid(x, y))      return undefined
    else if (exists(x, y)) return a[x][y]
    else                   return v_default
  }

  // Private setter
  // - Returns the value set on success.
  // - Returns `undefined` on failure
  function set (x, y, v) {
    if (valid(x, y)) {
      // We're being lazy
      if (!a[x]) a[x] = []
      a[x][y] = v
      return a[x][y]
    }
    return undefined
  }

  // Return an interface function. 
  // - Pass the function three arguments, (x, y, v), to set a[x][y] = v
  // - Pass the function two arguments, (x, y), to get a[x][y]
  return function (x, y, v) {
    if (arguments.length > 2) {
       return set(x, y, v)
    } else {
       return get(x, y)
    }
  }
})(100, 100)

When I ran the above in node, the following tests printed sensible values:

// Invalid invocations
console.log('map()                : %s', map())
console.log('map(  0)             : %s', map(0))
console.log('map( -1,   0)        : %s', map(-1,0))
console.log('map(  0,  -1)        : %s', map(0, -1))
console.log('map( -1,  -1)        : %s', map(-1, -1))

// Valid invocations
console.log('map(  0,   0)        : %s', map(0, 0))
console.log('map( 99,  99)        : %s', map(99, 99))
console.log('map(  1,   1)        : %s', map(1,1))
console.log('map(  1,   1, "foo") : %s', map(1,1, 'foo'))
console.log('map(  1,   1)        : %s', map(1,1))

Upvotes: 46

Koen Peters
Koen Peters

Reputation: 12916

You're feeding the world_map_array[i] expression a value for i that does not exist in world_map_array. So I guess x_world_map_titles is > 2.

I think you need to rewrite i<=2 to i<=x_world_map_titles

Also you do not need to specify the size of the array. I would just use literals in this case:

var x_world_map_tiles = 100;  
var y_world_map_tiles = 100; 

var world_map_array = [];
for (i=0; i<=x_world_map_tiles; i++)
  //create a two dimensional array of 101x101 so can access the map through x and y coords map_array[0][1] etc. { 
  world_map_array[i]=[];
}

for (i=0; i<=x_world_map_tiles; i++)//just a test { 
  for (z=0; z<=y_world_map_tiles; z++)//just a test { 
    world_map_array[i][z]="grass.gif|ongrass.gif|collision.gif|above.gif"; 
  }
}

Upvotes: 0

Danilo Valente
Danilo Valente

Reputation: 11352

var x_world_map_tiles = 100;
var y_world_map_tiles = 100;
var world_map_array = new Array(x_world_map_tiles);
for (i=0; i<=2; i++)//create a two dimensional array 
{
    world_map_array[i]=new Array(y_world_map_tiles);
}
for (i=0; i<x_world_map_tiles; i++)
{
    for (z=0; z<y_world_map_tiles; z++)
    {
        world_map_array[i][z]="grass.gif|ongrass.gif|collision.gif|above.gif";
    }
}

As your array has a length of 100, you must go from 0 to 99 (<100) and not to 100 (<=)

Upvotes: 3

Engineer
Engineer

Reputation: 48813

This

for (i=0; i<=2; i++)

must be:

for (i=0; i<=x_world_map_tiles ; i++)

Upvotes: 2

Related Questions