2012-05-20 19 views
12

私は、この行に何らかの理由でエラーにキャッチされない例外TypeError:プロパティを設定することはできません '0' 未定義の「

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

ですが、なぜでしょう

Uncaught TypeError: Cannot set property '0' of undefined

を取得しています?助けてくれてありがとう

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

* world_map_array 'ので、[i]は、'いくつかの点で 'undefined'はこの出来事*であるのはなぜ?。配列の長さが例えば3の場合、インデックスは '0'、' 1'、 '2'です。また、インデックスに値を割り当てなかった場合、それは 'undefined'になります。 –

+0

どうすればこの問題を解決できますか? – user1406186

+0

私がしようとしているのは、タイルマップを表す2次元配列を作成することです。例えば[0,0] [1,0] [2,0] [0,1] [1,1] [2,1] [0,2] [1,1] [2,2] ' – user1406186

答えて

26

配列は、あなたが他の言語から来た場合、あなたが期待できないことを自分自身の癖を持っています。あなたのユースケースで重要なものは、

  1. です。JavaScriptで多次元配列を直接宣言することはできません。
  2. 作成時にアレイのサイズを設定すると、効率上の利点はほとんどなく(安全性も向上しません)

JavaScriptは他の言語とは異なり、完全な配列に対して1ブロックのメモリを割り当てません。 (各セルに入れようとしているオブジェクトの種類はわかりません。 )合計のメモリ容量はどれくらいですか? 代わりにArray()へのsizeの引数はすべて、 lengthプロパティ。一般的な、2次元配列の場合については

、私がお勧めしたい:

  1. を必要に応じて "トップ" 配列、例えば:

    var i  // the first-order index in a 
        , j  // the second order index in a 
        , a = [] 
    
  2. 初期化配列の要素を作成します。 これはlazy initialization, と呼ばれ、この場合はa[i][j]に何かを割り当てる前に、a[i]が存在することを単にテストすることが含まれます。 :上記の文は読み、英語で

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

    : 「をaのi番目の要素は 『falsy』である場合、i番目の要素に空の配列を割り当てます。」

  3. 最後に、multideminsional配列に実際の値を代入:あなたのケースのために

    a[i][j] = 'whatever' 
    

、あなたが先に時間の値を知って、 ますので、事前に各要素を初期化することができます。 (あなたはしかし、要素のほとんどをオーバーライドしていない場合、 怠惰な実装が良いかもしれません。下記参照。)100個の要素を持つ配列がインデックスから番号を付けたいくつかの他の人が言ったように

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

ゼロ~,99,ここでは、より小さい比較が最も適切です。


参考までに、遅延初期化を使用した実装について説明します。 私は、配列に直接アクセスするのではなく、関数インタフェースを使いました。 それは長くて複雑ですが、より完全です。

私がここで使用した初期化パターンは、 immediately invoked function expressionと呼ばれています。 これまで見たことがない人は、 より便利なJavaScriptパターンの1つで、 と理解しておく価値があります。

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) 

私はノードで上記を実行した

、次のテスト印刷賢明な値:

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

でなければなりません:

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

いいえ、 'for(i = 0; i

+0

@FelixKling下記の 'for(i = 0; i <= x_world_map_tiles; i ++)//ただのテストを参照してください。 – Engineer

+0

OK、合意しました、うまくいくでしょうが、実際には間違っています;) –

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

あなたの配列は、100の長さを持っているとして、あなたは990から行かなければならない(< 100)とではないに100(< =)

0

world_map_array[i]式には、の値があり、には含まれていません。world_map_array。だから、私はまた、あなたは、配列のサイズを指定する必要はありませんi<=2

i<=x_world_map_titlesにを書き換える必要があると思う x_world_map_titlesは> 2.

だと思います。私はこのケースではリテラルを使用します。JavaScriptで

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"; 
    } 
} 
関連する問題