JavaScriptの配列をも〜っと深く理解する:lengthの不思議な動作

白石俊平(あゆた)
2008-02-08 11:00:00
不思議な挙動をするlengthプロパティを極めて、JavaScriptの配列を卒業するとしよう。
最新特集【一覧】

 配列オブジェクトの中に格納されている値の個数は、現在4つのはずです。lengthが「配列の長さ」を表すのであれば、「4」が表示されてもおかしくはありません。

 しかしこれは、試してみればすぐわかるのですが、答えは「1001」となります。「配列の長さが1001」ということは、「a[1000] = 500」を行った瞬間にオブジェクト1000個分の領域が確保されてしまったのでしょうか?

 幸いなことに、そうではありません。in演算子を用いて、オブジェクトaに格納されているキーと値を調べてみることにします。

var tmpArray = [];
for (var key in a) {
    tmpArray.push(key);
}
// 結果は「0,1,2,1000」
alert(tmpArray.join());

 結果は「0, 1, 2, 1000」となります。つまり、lengthの値が1001を表しているのに、実際配列に格納されている要素は4つしかないと言うことになります。

 従って、JavaScript配列のlengthプロパティは「配列にどれだけ値が格納されているか」を表すものではありません。結論を言うとlengthプロパティは、「インデックス最大値 + 1」を表す値で自動的に更新される特殊なプロパティなのです。「lengthはヘンなプロパティである」という意味がお分かりいただけたのではないでしょうか。

 ※このことから、配列の値を走査する場合は「for (var i = 0; i < a.length; i++)」とやるよりも、in演算子を用いた方が速いことが多いです。上の例で言えば、前者の場合1000回ループしますが、後者の場合は4回で済むのですから。ただし、配列の添え字を飛び飛びで使用することはあまりないでしょうから、気にする状況は限られてくるでしょう。

添え字として無効なキーは、lengthに影響を与えない

 これも実験するとすぐわかりますが、配列添え字として無効なキー(2の32乗までの正数以外)を配列オブジェクトに格納しても、lengthプロパティは変化しません。

var a = [];     // lengthは0
a[0] = "aaa";   // lengthは1になる
a["1"] = "bbb"; // lengthは2になる。文字列も有効
a["a"] = "ccc"; // "a"は添え字として無効なので、lengthは変化しない

lengthプロパティは書き込みも可能

 lengthプロパティは、読み取りを行えるだけではありません。lengthプロパティに数値を代入すると、その大きさまで配列は切り詰められます。

var a = [1, 2, 3, 4];
a.length = 0;   // 空の配列になる

 配列を一定の長さに保ちたい、という場合などに役立つテクニックです。

まとめ

 さて前回と今回は、JavaScriptの配列とはいかなるものか、ということを掘り下げて説明しました。以下は前回の記事の冒頭に記した、JavaScript配列に関するまとめです。記事が二回にわたってしまったので、最後にもう一度確認の意味で掲載しておくとしましょう。

  1. JavaScript配列は、Cのように値を複数格納できる「連続したメモリ領域」とはまったく違う 。配列はJavaScriptオブジェクトであり、つまりハッシュテーブルである
  2. 配列の添え字はハッシュのキーである。JavaScriptオブジェクトのキーには数値も使える事を押さえておこう(連載第三回参照)
  3. 極めて特殊なlengthプロパティを持つ。lengthプロパティは、「インデックス最大値 + 1」を表すプロパティ
  4. lengthプロパティは読み取りだけでなく書き込みも可能。書き込むと、その大きさまで配列が切り詰められる

配列は非常に良く使用するデータ構造なので、ここで学んだ深い知識が役に立つときは必ずあります。しっかり身につけておくと良いでしょう。

次回からはいよいよ、JavaScriptのオブジェクト指向機能についてお話ししていきたいと思います。コンストラクタやプロトタイプについて詳しく学んでいきましょう。