21

エラーが発生します

Uncaught TypeError:未定義のプロパティ「0」を設定できません

この行の何らかの理由で

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

なぜこうなった?

助けてくれてありがとう

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

5 に答える 5

46

JavaScriptの配列には、他の言語から来た場合には予​​期しない可能性のある独自の癖があります。ユースケースにとって重要なものは次の2つです。

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

他の言語とは異なり、JavaScriptは完全な配列にメモリのブロックを割り当てません。(各セルに配置するオブジェクトの種類、したがって必要な合計メモリ量はわかりません。)代わりに、実行するすべてのsize引数Array()は配列のlengthプロパティを設定します。

一般的な2次元配列の場合、次のことをお勧めします。

  1. 「トップ」配列を作成します。例:

    var i       // the first-order index in a
      , j       // the second order index in a
      , a = []
    
  2. 必要に応じて配列要素を初期化します。これはレイジー初期化と呼ばれ、この場合、a[i]何かを割り当てようとする前に存在するテストが含まれますa[i][j]。例:

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

    英語では、上記のステートメントは次のようになります。「のi番目の要素aが'falsy'の場合、i番目の要素に空の配列を割り当てます。」

  3. 最後に、実際の値を多次元配列に割り当てます。

    a[i][j] = 'whatever'
    

あなたの場合、事前に値を知っているので、各要素を事前に初期化することができます。(ただし、ほとんどの要素をオーバーライドしない場合は、遅延実装の方が適している可能性があります。以下を参照してください。)

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

他の人が言っているように、100個の要素を持つ配列には、0から99までの番号が付けられたインデックスがあるため、ここでは、より少ない比較が最も適切です。


参考までに、レイジー初期化を使用する実装を次に示します。配列に直接アクセスする代わりに、関数インターフェースを使用しました。それはより長く、より複雑ですが、より完全でもあります。

ここで使用した初期化パターンは、 即時呼び出し関数式と呼ばれます。これまでに見たことがない場合は、これはより便利な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))
于 2012-05-20T17:27:37.723 に答える
3
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であるため、 (<=)ではなく(<100)0に移動する必要があります。99100

于 2012-05-20T12:09:02.873 に答える
2

これ

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

でなければなりません:

for (i=0; i<=x_world_map_tiles ; i++)
于 2012-05-20T12:08:48.643 に答える
0

に存在しない world_map_array[i]値を式にフィードしています。だから私は>2だと思います。iworld_map_arrayx_world_map_titles

私はあなたがに書き直す必要があると思いi<=2ますi<=x_world_map_titles

また、配列のサイズを指定する必要はありません。この場合、リテラルを使用します。

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"; 
  }
}
于 2012-05-20T12:10:25.273 に答える
-1

javascriptで2次元配列を使用しているときにUncaughtTypeErrorを取得します。

2次元配列の場合、最初に親配列を宣言します

var arryTwoDimension = [];

次に、状況に応じて、次の方法で子配列を作成できます。

arryTwoDimension [i]=[]私は0,1,2......からなります。

これで問題は解決します。

于 2018-04-11T10:08:12.797 に答える