LoginSignup
30
27

More than 5 years have passed since last update.

配列名にnameを使用するとfor-inで期待の動作をしない問題

Last updated at Posted at 2016-01-02

下記コードの様に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>

参考ページ
https://teratail.com/questions/16647

30
27
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
27