下記コードの様にJavaScriptでfor-inで回して順に配列の中身を順に取り出そうとするも配列の要素の1字ずつが取り出されてしまう。
<script>
var name = ['山田', '佐藤', '鈴木'];
for(var i in name) {
document.write(name[i] + 'です。' + '<br>');
}
</script>
出力結果
山です。
田です。
,です。
佐です。
藤です。
,です。
鈴です。
木です。
勿論、期待していた出力結果は以下の通りです。
出力結果
山田です。
佐藤です。
鈴木です。
まずnameの変数名をname1とかに変えてみる
<script>
var name1 = ['山田', '佐藤', '鈴木'];
for(var i in name1) {
document.write(name1[i] + 'です。' + '<br>');
}
</script>
出力結果
山田です。
佐藤です。
鈴木です。
期待通りの出力がされた様です。
しかしこれだと何故このような結果に至ったのか、何故変数名をnameをname1に変えると上手くいくのかが納得がいかなかった為、もう少し調査してみました。
するとこんな仕様が見つかりました。
https://developer.mozilla.org/ja/docs/Web/API/Window/name
これによると、window.nameというグローバルオブジェクトwindowのプロパティがあるということです。
つまりこれが何を意味しているのかというと、変数名をnameにしてしまうとグローバル変数であるwindow.nameと衝突してしまうということです。
※name1に変数名を変更すると衝突自体は回避出来る
そして、window.nameは仕様によるとString型に型変換されてしまう為、
window.name = ['山田', '佐藤', '鈴木']
としてしまうと、配列の各要素が取り出されるのではなく、1文字ずつが取り出されてしまうという結果に至るわけです。
※そもそもfor-inだとランダムに要素が取り出される可能性があるので、順番を変えたくない場合には適しません。
対処法
即時関数で囲った上でローカル変数を定義し、for-inではなく単純にfor文を利用する方法が一番簡単な解決法かと思います。
これによりwindow.nameとの衝突を回避出来るハズです。
<script>
(function () {
var name = ['山田', '佐藤', '鈴木'];
for (var i = 0, l = name.length; i < l; ++i) {
document.write(name[i] + 'です。' + '<br>');
}
}());
</script>