配列とカスタムオブジェクト(連想配列)

配列はArrayクラスのインスタンスです。ただし、以下の前提があります。

配列のインデックスは0から連続した自然数である

勘違いしがちなのは、lengthプロパティがオブジェクトのメンバ数を表す、と思ってしまうことです。実際には最大の自然数のインデックス+1の値が格納されます。上の前提により、これが配列の要素数を表すことになります。

var ary = new Array();
ary[-2] = "N"; //インデックスが自然数でないので配列の要素ではない。
ary[3] = "Y"; //配列の要素
ary[3.5] = "N"; //インデックスが自然数でないので配列の要素ではない。
alert(ary.length); //"4"と表示される。
                   //ary[3]があるとary[0],ary[1],ary[2]はあるとみなされる。
                   //ary[-2],ary[3.5]は要素としてカウントされない。

つまり、Arrayクラスのオブジェクトは、追加されるメンバのプロパティ名を監視し、それが自然数で、lengthプロパティ以上であった場合、lengthプロパティをその値+1に変更する、という機能を持っています。

var ary = new Array();
ary[2] = "Y"; 
alert(ary.length); //"3"と表示される。
ary[4] = "Y";
alert(ary.length); //"5"と表示される。
ary[3] = "Y";
alert(ary.length); //"5"と表示される。

配列の各要素を扱うコードは以下のようになります。*1

var ary = new Array();
ary[2] = "二"; 
ary[4] = "四";
for(var i = 0; i < ary.length; i++){
  if(!(i in ary)){ 
    continue; //メンバとして存在しなければ処理せず次の要素へ
  }
  alert(ary[i]); //'二', '四'が順に表示される。
}

ここでiの初期値をマイナスにしたり、i++をi+=0.5にしたりするのは適切でない、ということになります。また、ここでfor inループを使うのも適切ではありません。

配列の省略記法として以下があります。

var ary = ["零", "壱", "弐", "参"];

これは以下と同じです。

var ary = new Array();
ary[0] = "零"; 
ary[1] = "壱";
ary[2] = "弐"; 
ary[3] = "参";

応用すると、多次元配列も簡単に書けるようになります。

var ary = [0, [10, 11], [[200, 201], [210, 211]]];
alert(ary[2][0][1]); //'201'が表示される

次に、カスタムオブジェクト(連想配列)です。こちらは配列のようにlengthが自動的に更新されるような機能を持ちませんので、オブジェクトのすべてのメンバを処理するためにはfor inループを使います。

var obj = new Object();
obj.zero = "零";
obj.one = "壱";
obj.two = "弐";
obj.three = "参";
for(var i in obj){
  alert(i + ":" + obj[i]);
  //"zero:零","one:壱","two:弐","three:参"が順に表示される
}

obj.zeroをobj["zero"]と書いても同じです。違いとして、前者には変数として許容できる名前のみが使用できるのに対し、後者はほぼ何でも設定が可能、ということです。また、変数の値の文字列を使用したい場合にも有効です。

obj["zero"] = "零";
obj[1] = "壱";
//obj.1 = "壱"; →これはだめ。1は変数名にならない。
obj["弐"] = "弐";
var str = "three"
obj[str] = "参";

カスタムオブジェクトの省略記法として以下があります。

var obj = {zero:"零", one:"壱", two:"弐", three:"参"};

プロパティ名を"や'でくくれば日本語や空白も設定可能です。配列と同様、入れ子にすることができます。

var obj = {zero:"零", one:{two:"壱弐", three:"壱参"}};
alert(obj.one.two); //"壱弐"と表示される。

*1:要素の存在判定を==nullで行っていたのをinに置き換えました。こちらのほうが妥当だと思います。