結論から言うと、見かけ上使えますがそれは配列ではなく配列のプロパティです. それに気づくまでのメモを残しておきます.
クラスの関係
前提として、JavaScriptではArrayクラスはObjectクラスの子クラスであるFunctionクラスの子クラスです(Object <-- Function <-- Array). つまり、ArrayクラスはObjectクラスでもあります.
したがって、Objectクラスのインスタンス(以降オブジェクト)でできることはArrayクラスのインスタンス(以降配列)でもできます.
連想配列はオブジェクトのプロパティ
JavaScriptでは次のようにしてプロパティを追加することが出来ます.
const obj = new Object(); // same with const obj = {}; obj['hoge'] = 10; // same with obj.hoge=10
JavaScriptでは、キーと同じ名前のプロパティをオブジェクトに追加することで連想配列(のようなもの)を実装しています. 他の多くの言語ではハッシュを使い文字列を数値に変換することで連想配列を実装してると言いますが、この時点でかなり事情が異なることが分かります.
前述の通り配列にもプロパティを追加することが出来ます. したがって、次のコードは配列に要素を追加しているように見えますが、配列のプロパティを追加していることになります.
const arr = new Array(); // same with const arr = []; arr['fuga'] = 10; // same with arr.fuga = 10;
このことを確かめるために、以下のようなコードを実行しましょう.
const arr = [] arr['fuga'] = 10; arr[0] = 20; arr[1] = 30; console.log("length of arr is:" + arr.length); //length of arr is:2
結果は「 length of arr is:2 」と表示されます. このことから、配列のキーを文字列にした場合、それは配列に要素を追加したわけではないということが明らかになりました.
for...inとfor...of
for...inはオブジェクトのプロパティを走査するための構文で、for...ofはStringやArrayやSetなどの反復可能オブジェクトを走査するための構文です. つまりは、for...inは任意のオブジェクトに対して使え、for...ofはiterableなオブジェクトに対して使えます. 次のコードを実行すると、forループの順番をどのようにしても「Uncaught TypeError: obj is not iterable」というエラーが表示されます.
const arr = []; const obj = {}; for(const i of obj){ console.log("const i of obj"); // Uncaught TypeError: obj is not iterable } for(const key in obj){ console.log("const key in obj"); } for(const i of arr){ console.log("const i of arr"); } for(const key in arr){ console.log("const key in arr"); }
配列のfor...inを実行するときの注意ですが、配列の要素の方も走査されるようなので気をつけましょう. 次のコードを実行すると、予想に反してfor...inのループが3回実行されます. このことからJavaScriptに限って言えば、配列は0以上の非負整数を名前に持つ特別なプロパティと考えるのが良いのかもしれません.
const arr = []; arr['fuga'] = 10; arr[0] = 20; arr[1] = 30; for(const i of arr){ console.log("array elem: " + i); } for(const key in arr){ console.log("property: " + key); } /* 実行結果 main.js:7 array elem: 20 main.js:7 array elem: 30 main.js:11 property: 0 main.js:11 property: 1 main.js:11 property: fuga */
以上から、とりあえず以下のようなイメージでよいのではないかと思います.