皆さんJavaScriptで配列の要素数を知りたい時はlengthプロパティを参照しているかと思います。
しかし、このlengthプロパティですが、実は配列の要素数の値では無いんです。
今回のエントリーでは、そんなlengthプロパティの動作をソースコード付きで解説したいと思います。
以下サンプルコード
<script type="text/javascript"> //配列を作成(要素は二つ) var array = ["aaa","bbb"]; //出力を期待する数値は2 alert(array.length); //配列に値を追加(要素は三つになる) array.push("ccc"); //出力を期待する数値は3 alert(array.length); //要素数を加味し、重複しない添え字に要素を追加する(要素は四つ) array[10] = "ddd"; //出力を期待する数値は4 alert(array.length); </script>
単純に配列を定義し、配列に要素を追加しながら要素数をalertで表示していくシンプルなコードです。
lengthプロパティが配列の要素数であれば、コメント通りの期待値が出力されるはずです。
しかし、実際には期待通りの値は出力されません。
そのまま実行させて見るとわかると思いますが、
期待値として『4』を望む所で『11』と表示されるかと思います。
これは不思議ですね。
要素数は『4』の筈なのに『11』とされているという事は、空の要素で『11』まで埋め尽くされているのでしょうか。
確認して見ましょう。
<script type="text/javascript"> //配列を作成(要素は二つ) var array = ["aaa","bbb"]; //出力を期待する数値は2 alert(array.length); //配列に値を追加(要素は三つになる) array.push("ccc"); //出力を期待する数値は3 alert(array.length); //要素数を加味し、重複しない添え字に要素を追加する(要素は四つ) array[10] = "ddd"; //出力を期待する数値は4 alert(array.length); //配列をinで回し、キーと値を出力します for(var key in array){ alert(key +" : "+array[key]); } </script>
配列の要素をループで出力して確認して見ました。
すると、下記の様にアラートが出力されるはずです。
0:aaa
1:bbb
2:ccc
10:ddd
『11』まで空の要素で埋め尽くされているわけではなく、
添え字と要素は期待通りの出力となったかと思います。
では何故lengthプロパティは『11』となるのでしょうか。
それは、実はlengthプロパティは配列の要素数を保持しているのでは無く、
【配列に定義されているインデックスの最大値に1を足し込んだ数値を保持しています】
また、lengthプロパティはインデックスの最大値が影響するので、
インデックス以外の添え字ではlengthプロパティに影響はしません。
ですので、添え字を文字として扱う連想配列として使用する際には注意が必要です。
例えば下記の様なパターンです。
<script type="text/javascript"> //配列を作成(要素は二つ) var array = ["aaa","bbb"]; //出力を期待する数値は2 alert(array.length); //配列に値を追加(要素は三つになる) array.push("ccc"); //出力を期待する数値は3 alert(array.length); //要素数を加味し、重複しない添え字に要素を追加する(要素は四つ) array["key"] = "ddd"; //配列をinで回し、キーと値を出力します for(var key in array){ alert(key +" : "+array[key]); } //出力を期待する数値は4 alert(array.length); </script>
先ほどのコードのキーが『10』だった所を『key』という文字列とした連想配列にしました。
このコードを実行すると、またまた不思議な現象が起こります。
inループで中身を出力して見ると、確かに
0:aaa
1:bbb
2:ccc
key:ddd
となっており、要素数は『4』を期待するかと思います。
しかし、今回は要素数が『3』と出力されます。
これは、『key』という添え字がインデックス数では無い事が原因です。
ですので、連想配列を使用する際にはlengthプロパティは使い物になりません。
気をつけましょう。
そして、lenghtプロパティはプロパティですので、プロパティに値を新たに上書きする事も出来ます。
試しに新たにlengthプロパティの値を上書きして見ましょう。
<script type="text/javascript"> //配列を作成(要素は二つ) var array = ["aaa","bbb"]; //出力を期待する数値は2 alert(array.length); //配列に値を追加(要素は三つになる) array.push("ccc"); //出力を期待する数値は3 alert(array.length); //要素数を加味し、重複しない添え字に要素を追加する(要素は四つ) array[10] = "ddd"; //配列をinで回し、キーと値を出力します for(var key in array){ alert(key +" : "+array[key]); } //出力を期待する数値は4 alert(array.length); //lengthプロパティを上書きする array.length = 1; //配列をinで回し、キーと値を出力します for(var key in array){ alert(key +" : "+array[key]); } </script>
lengthプロパティを上書きすると、その時点で上書きされた数値までインデックス数を切り詰める為、
この場合はでは要素は一つだけとなります。
しかし、連想配列の場合では、インデックスの切り詰めも影響しないので、
このコードに加えて連想配列を追加した場合、インデックス要素の値一つと、
連想配列の要素全てが配列に残る事となります。
やはり連想配列を扱い場合はlengthプロパティは要注意ですね。
知らずに使うと思わぬバグを生む可能性があります。
手軽に使えるプロパティだからこそ、使い方、使い所に注意して、
しっかりとした動作理解の元、使用したいですね。
3つめのサンプルコードの下の説明、
返信削除> inループで中身を出力して見ると、確かに
>
> 0:aaa
> 1:bbb
> 2:ccc
> 10:ddd
>
> となっており、要素数は『4』を期待するかと思います。
とあるけど、key:ddd じゃないのかな?
この度はコメント頂きまして、誠に有難うございます。
削除ご指摘のとおり、確かに表記が間違っていましたので、
早速ですが修正させて頂きました。
他にも何か御座いましたら
お手数お掛けしますが、ご報告頂ければ幸いです。
今後ともよろしくお願いいたします。