2012-05-20 12 views
12

Estoy consiguiendo el errorTypeError no detectada: No se puede establecer la propiedad '0' de la indefinida "

Uncaught TypeError: Cannot set property '0' of undefined

por alguna razón en esta línea

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

por qué sucede esto

? gracias por cualquier ayuda

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"; 
} 
} 
+1

* Por qué sucede esto * Debido 'world_map_array [i]' 'es undefined' en algún momento?. Si una matriz tiene longitud, digamos, '3', entonces los índices son' 0', '1',' 2'. Además, si nunca asignó un valor a un índice, será 'undefined'. –

+0

¿cómo arreglaría esto? – user1406186

+0

lo que estoy tratando de hacer es crear una matriz bidimensional para representar un mapa de teselas. p.ej. '[0,0] [1,0] [2,0] [0,1] [1,1] [2,1] [0,2] [1,1] [2,2] ' – user1406186

Respuesta

26

matrices en JavaScript tienen peculiaridades propias que no se puede estar esperando si viene de otros idiomas. Dos importantes para su caso de uso son:

  1. No puede declarar directamente matrices multidimensionales en JavaScript.
  2. Hay poco beneficio de eficiencia (y ninguna seguridad añadida) cuando configura el tamaño de la matriz en la creación.

A diferencia de otros idiomas, JavaScript no asignará un bloque de memoria para la matriz completa. (No sabe qué tipo de objetos va a poner en cada celda, y, por lo tanto, cuánta memoria total necesitará) En su lugar, todo el argumento size para Array() hace por usted se establece la matriz length propiedad.

Para el, caso general matriz 2D, me gustaría sugerir:

  1. crear la matriz "de arriba", por ejemplo .:

    var i  // the first-order index in a 
        , j  // the second order index in a 
        , a = [] 
    
  2. elementos de la matriz de inicialización, según sea necesario. Esto se llama lazy initialization, y, en este caso, solo implica la prueba de que a[i] existe antes de intentar asignar algo a a[i][j], p. Ej.:

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

    En Inglés la declaración anterior se lee: "Si el i-ésimo elemento de a es 'Falsy', asignar una matriz vacía al elemento i-ésimo."

  3. Por último, asigne el valor real de la matriz multideminsional:

    a[i][j] = 'whatever' 
    

Para su caso, conocer los valores antes de tiempo, por lo que puede inicializar cada elemento de antemano. (Si usted no está anulando la mayor parte de los elementos, sin embargo, una implementación perezoso puede ser mejor; ver más abajo.)

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' 
    } 
} 

Como otros han dicho, una matriz con 100 elementos numerados de índices ha cero a noventa y nueve, por lo que una comparación menor que la más adecuada aquí.


Como referencia, aquí hay una implementación que usa la inicialización diferida. He ido con una interfaz de función en lugar de acceder directamente a la matriz; es más largo y más complejo, pero también más completo.

El patrón de inicialización que he usado aquí se llama immediately invoked function expression. Si no lo ha visto antes, es uno de los patrones de JavaScript más útiles y vale la pena tomarse un tiempo para comprenderlo.

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) 

Cuando me encontré con lo anterior en el nodo, las siguientes pruebas impresas valores razonables:

// 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)) 
2

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

debe ser:

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

No, debe ser 'for (i = 0; i

+0

@FelixKling Consulte ''para (i = 0; i <= x_world_map_tiles; i ++) // solo una prueba' 'a continuación. – Engineer

+0

Ok, de acuerdo, funcionaría, pero eso también es incorrecto;) –

2
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"; 
    } 
} 

medida que su matriz tiene una longitud de 100, usted debe ir de 0 a 99 (< 100) y no a 100 (< =)

0

Está alimentando la expresión world_map_array[i] un valor para i que no existe en world_map_array. Así que supongo que está x_world_map_titles> 2.

creo que es necesario volver a escribir i<=2 a i<=x_world_map_titles

también que no es necesario especificar el tamaño de la matriz. Yo sólo tiene que utilizar literales en este caso:

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"; 
    } 
} 
Cuestiones relacionadas