【JavaScript】Array.lengthの不可解な挙動

1 min read読了の目安(約1700字

問題

突然ですが以下のlengthの値ってどうなると思いますか?

const array = [];
array['book'] = 'santai';
console.log(array); // [ book: 'santai']
console.log(array.length); // …?

ぜひ、ちょっと考えてみてください。

think_neko

答えは0です。

console.log(array.length); // 0

筆者はundefinedだと思ったのですがJavaScriptの仕様では0になるようです。他にも1になるのではと考えた人もいるんじゃないでしょうか?

最初から処理を追って行ってみましょう。
まずJavaScriptでは配列にプロパティを追加することができてしまうみたいです。

array['book'] = 'santai';
console.log(array); // [ book: 'santai']

この時点で配列は連想配列に変化すると思っていたのですが、どうやら配列のままのようです。

console.log(Array.isArray(array)); // true

もしも配列が連想配列に変化していたのなら、lengthプロパティを呼び出すとundefinedが返ってくるはずです。

const obj = {};
console.log(obj.length); // undefined

配列のままなので正常にlengthプロパティを呼び出すことができ、答えは1になる……と思いきや帰ってきたのは0

console.log(array.length); // 0

どうやらlengthは配列内に数値以外のキーがあった場合、それを検知できないみたいです。

const array = [];
array['book'] = 'santai';
array.push(1)
console.log(array); // [ 1, book: 'santai' ]
console.log(array.length); // 1

MDNを漁ってみたのですがこのような仕様について記述してある項目は見つからず……。どなたか詳しく書いてある文献を知っていたら教えてください<(_ _)>

解決策

解決策としてはObject.keys()を使えば期待するような結果が得られます。

const array = [];
array['book'] = 'santai';
console.log(array); // [ book: 'santai']
+ console.log(Object.keys(array).length); // 1
const array = [];
array['book'] = 'santai';
array.push(1)
console.log(array); // [ 1, book: 'santai' ]
console.log(Object.keys(array)); // [ '0', 'book' ]
console.log(array.length); // 2

参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/length