水無瀬のプログラミング日記

プログラムの勉強した時のメモ

Javascriptのfor系統まとめ(for,for..in,for..of,forEach)

TL;DR.

ソースコード
実行はNode.jsで。

はじめに

for...inとfor...ofどっちがどっちか忘れるからまとめる。
ついでに他のforについてもまとめて、個人的なメリットデメリットも記載する。

forの種類

  • for
  • for...in
  • for...of
  • Array.forEach()

for

単純なfor。指定した回数繰り返し処理をしてくれる。

// 単純ループ 
let sum = 0; 
for (let i = 1; i <= 10; i++) { 
    sum += i; 
} 

// リスト全ループ 
const list = [1, 3, 5, 7]; 
for (let i = 0; i < list.length; i++) { 
    console.log('value:', list[i]); 
} 

メリット

わかりにくいとかは無いと思う。
これといったメリットは思いつかなかった。

デメリット

いちいち書くのがめんどくさいと思う。

for...in

オブジェクトのプロパティ(キー)分ループしてくれる。

const obj = {'a':1, 'b':2, 'c':3}; 
for (const value in obj) { 
    console.log('key:', value); 
    console.log('value:', obj[value]); 
} 

メリット

オブジェクト(連想配列)のループができる。

デメリット

配列に使うとあんまりよくない。

const list = [1, 3, 5]; 
list.text = 'hoge'; 
list.func = function(){
    console.log('hoge');
}
for (const key in list) { 
    console.log('key:', key); 
    console.log('value:', list[key]); 
}

出力は下記の通り。
配列のループは直感だと値が逐次取れるイメージだと思う。
実際はindexが取れる。
しかも後から追加した変なのも普通に取れてしまう。

key: 0
value: 1
key: 1
value: 3
key: 2
value: 5
key: text
value: hoge
key: func
value: function (){
    console.log('hoge');
}

当たり前だけど、TypeScriptでも変わらない。

class test {
    constructor() {
        const list:number[] = [1, 3, 5];
        list['text'] = '1';
        for (const value in list) {
            console.log(value);
        }
    }
}

new test();

/*
  結果
  0
  1
  2
  text
*/

for...of

プロパティの値分ループするfor文。
Javaの拡張forが近しい動きだと思う。

const list = [1, 3, 5]; 
for (const value of list) { 
    console.log(value); 
} 

メリット

下みたいなことしても問題なく出力してくれる。

const list = [1, 3, 5]; 
list.text = '1'; 
for (const value of list) { 
    console.log(value); 
} 

デメリット

ES6で導入されたから、古いブラウザだと動かない。
ブラウザ変えろ。

Array.forEach

配列要素に対しての繰り返しを行ってくれるメソッド。
できることはfor...ofとほぼ同じ。

const list = [1, 3, 5]; 
list.forEach(element => { 
    console.log(element); 
}); 

callbackの引数全指定した場合は下記の通り。
下記例のarrayについては、特に何もしなければループ中同じ値が取れる。

const list = [1, 3, 5]; 
list.forEach((element, index, array) => { 
    // 取り出した配列の値 
    // 例:1,3,5 
    console.log('element:', element); 
    // 配列のインデックス 
    // 例:0,1,2... 
    console.log('index:', index); 
    // ループしてる配列自身 
    // 例:[1, 3, 5] 
    console.log('array:', array); 
}); 

メリット

indexを使うことができる。
(人によると思うけど)見やすい。
callbackだから関数を切り出せる。
(切り出されているところを見たこと無いし、for...ofでも同じ気がするけど)

const loop = element => { 
    console.log('callback:', element); 
} 
list.forEach(loop); 

デメリット

あくまでcallbackなので、breakできない。
※continueはreturnと書けばOK。
速度に不安があるみたいなので、速度が重要な 場合は使わないほうが無難だと思う。

おまけ

オブジェクトに対してforEachかけるなら、Object.keys()と組み合わせる。

const obj = { 'a': 1, 'b': 2, 'c': 3 }; 
Object.keys(obj).forEach(key => { 
    console.log('key:', key); 
    console.log('value:', obj[key]); 
}); 

まとめ

for...in以外ならどれでも良いと思う。
軽く調べた感じ、for...ofが優勢だった。
配列にしか使えないforEachと違って、
for...ofはiterable objectならなんでも使えるらしい。
更に速度面に不安なのもあると思われる。
個人的には速度をとても気にする必要もないし見やすいので、
breakする必要が無いならforEachを使ってる。