C/C++ プログラマのための JavaScript 入門: 連想配列と配列

no extension

オブジェクトの話の4回目で, とりあえず最終回です。 今回は連想配列と配列の話を中心に説明していきます。 例によって「プロローグ」で挙げた文献を頻繁に参照しています。 これらの文献を参照しながらご覧になることをお薦めします。

「データ型」の回では「オブジェクトは連想配列として扱うことができます」と書きましたが, 厳密には「オブジェクトは連想配列の内部表現を持つ」と言えます。 プロパティとして使えない(識別子の文字列規則を逸脱している)名前だったり, 設計時には名前を特定できない場合には連想配列の形式で処理するほうが合理的です。 連想配列のリストを取り出すには for/in 文を使います。

var point = { x:1 , y:2 };
for(var name in point) {
  WScript.Echo(name + " = " + point[name]);
}

ただし for/in 文では組み込みのプロパティやメソッドは(ほぼ)取り出せません。

実は, 初期の JavaScript では連想配列と配列は全く区別されていなかったそうです。 例えば

var obj = new Object(); //古い JavaScript では Array コンストラクタはなった
obj.name = "Spiegel";
obj[0] = "Baldanders"; // obj.name を上書き obj.name=="Baldanders"

といったことが起こるため, コーディングで両者を区別する必要がありました。 現在のバージョンではそのようなことはありません。

var a = new Array();
a["00"] = "member1";
a["01"] = "member2";
a[0] = "array";
WScript.Echo("a[0] = " + a[0]); // array
WScript.Echo("a[\"0\"] = " + a["0"]); // array
WScript.Echo("a[\"00\"] = " + a["00"]); // member1
WScript.Echo("a.length = " + a.length); // 1

といった感じで両者は区別されます。 配列表現は Array コンストラクタを使わなくても可能ですが, 配列としての機能は不完全です。

var a = new Object();
a["00"] = "member1";
a["01"] = "member2";
a[0] = "array";
WScript.Echo("a[0] = " + a[0]); // array
WScript.Echo("a[\"0\"] = " + a["0"]); // array
WScript.Echo("a[\"00\"] = " + a["00"]); // member1
WScript.Echo("a.length = " + a.length); // undefined

実は ECMAScript の言語仕様には配列や関数というデータ型は存在しません。 配列に似たもので「リスト(List Type)」はあるのですが, どうも関数呼び出し時に生成される実引数リストの評価の説明に使われる型のようです。 (ECMAScript では説明上の型を除いて「データ型」と呼んでいるものは, Undefined, Null, Boolean, String, Number, Object の6つしかありません。 このシリーズでは「プロローグ」で紹介した『JavaScript』を教科書代わりにしているので, ECMAScript の説明とは異なっています)

関数や配列は(データ型としての)オブジェクトのバリエーションとして考えることができます。 関数オブジェクトがオブジェクトとして振る舞うように, 配列もオブジェクトとして振る舞います。 完全な機能を持つ配列インスタンスを得るには Array コンストラクタが必要になります(またはリテラル表現で初期化します)。 完全な機能を持つ配列インスタンスでは配列操作に必要なプロパティ(length など)やメソッドが使えるようになります。 またメソッドをうまく使うことによってスタックやキューのように振る舞うことができます。 以下のページに配列操作の一覧が紹介されています。 他の言語との比較表になっているのでイメージしやすいと思います。

さて, 今回で一応区切りをつけることにします。 (ガベージコレクションや正規表現など)説明していないことは多々ありますが, それらについては「プロローグ」で紹介した文献が参考になると思います。 また気になるトピックが出てきた場合は追補していく予定です。

現在いろいろ調べていて気になっているのは, コアの JavaScript (ECMAScript)といわゆる「クライアントサイド JavaScript」(DOM など)との仕様のずれです。 このシリーズではコア JavaScript をターゲットに説明してきましたのでクライアントサイドについては一切スルーでした。 ただこの辺の話になると Tips 的な内容に偏ってしまいそうなので, むしろ他サイトのコンテンツをブックマークしていくほうが賢いかもしれません。 ブックマークについては del.icio.us で少しずつ収集していますので, 併せて参考にしていただければ幸いです。