2012-05-20 17 views
12

Dostaję błądUncaught TypeError: nie można ustawić właściwość '0' undefined "

Uncaught TypeError: Cannot set property '0' of undefined

z jakiegoś powodu w tym wierszu

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

Dlaczego tak się dzieje

? dzięki za pomoc

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

* Dlaczego tak się dzieje * Ponieważ 'world_map_array [i]' 'undefined' jest w pewnym momencie?. Jeśli tablica ma długość, powiedzmy "3", wówczas indeksy to '0',' 1', '2'. Ponadto, jeśli nigdy nie przypisałeś wartości do indeksu, będzie to "niezdefiniowana". –

+0

jak to naprawić? – user1406186

+0

co próbuję zrobić, to utworzyć dwuwymiarową tablicę do reprezentowania mapy kafelków. na przykład "[0,0] [1,0] [2,0] [0,1] [1,1] [2,1] [0,2] [1,1] [2,2] ' – user1406186

Odpowiedz

26

Tablice w JavaScript mają własnych dziwactw, że nie można oczekiwać, jeśli pochodzą z innych języków. Dwa ważne dla twojego przypadku użycia to:

  1. Nie możesz bezpośrednio zadeklarować tablic wielowymiarowych w JavaScript.
  2. Przy ustawianiu rozmiaru macierzy przy tworzeniu jest niewielka korzyść pod względem wydajności (i braku dodatkowego bezpieczeństwa).

W przeciwieństwie do innych języków, JavaScript nie przydzieli bloku pamięci dla pełnej tablicy. (Nie wie, jakie obiekty będą umieszczane w każdej komórce, , a zatem ile całkowitej pamięci będzie potrzebować.) Zamiast tego, cały argument size dla Array() robi dla ciebie zestaw tablic Właściwość length.

W ogólnym przypadku, 2d tablicy, którą proponujemy:

  1. Utwórz tablicę "top", np .:

    var i  // the first-order index in a 
        , j  // the second order index in a 
        , a = [] 
    
  2. Initialize elementów tablicy, ile potrzeba. Nazywa się to lazy initialization,i w tym przypadku wymaga to po prostu sprawdzenia, czy a[i] istnieje zanim spróbujemy przypisać coś do a[i][j], np.:

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

    W angielskim powyższe stwierdzenie brzmi: „Jeśli element i-ty z a jest«falsy»przypisać pustą tablicę do elementu i-tej”.

  3. Wreszcie, należy przypisać wartość rzeczywistą do multideminsional tablicy:

    a[i][j] = 'whatever' 
    

Twoim przypadku, wiesz wartości wyprzedzeniem, więc można zainicjować każdego elementu z góry. (Jeśli nie jesteś przesłanianie większość elementów, jednak leniwy realizacja może być lepiej; patrz poniżej.)

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

Jak niektórzy mówili inni, tablicą z 100 elementów został indeksy ponumerowane od zero do dziewięćdziesiąt dziewięć, więc porównanie poniżej jest najbardziej odpowiednie tutaj.


Dla odniesienia, oto implementacja, która używa leniwego inicjowania. Poszedłem z interfejsem funkcji zamiast bezpośredniego dostępu do tablicy; jest dłuższy i bardziej złożony, ale także bardziej kompletny.

Wzorzec inicjalizacji, którego tu użyłem, nazywa się immediately invoked function expression. Jeśli jeszcze tego nie widziałeś, to jest to jeden z bardziej użytecznych wzorców JavaScriptu i warto poświęcić trochę czasu, aby go zrozumieć.

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) 

Kiedy wpadłem wyżej w węźle, następujące testy drukowane wartości rozsądni:

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

to

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

musi być:

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

Nie, musi to być 'for (i = 0; i

+0

@FelixKling Zobacz ''dla (i = 0; i <= x_world_map_tiles; i ++) // tylko test'' w niżej. – Engineer

+0

OK, zgodzili się, że to zadziała, ale to jest właściwie niepoprawne;) –

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

Jak twoja tablica ma długość 100, trzeba iść z 0 do 99 (< 100) i nie 100 (< =)

0

Podajesz wyrażenie world_map_array[i] wartość dla i, która nie istnieje w world_map_array. Więc myślę, że jest x_world_map_titles> 2.

myślę, że trzeba przepisać i<=2 do i<=x_world_map_titles

Również nie trzeba określić rozmiar tablicy. Chciałbym po prostu użyć literałów w tym przypadku:

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"; 
    } 
} 
Powiązane problemy