forEachとforとforinの速度テスト

追記 20120329：その後、調べ直した結果 forEachよりforが早いというのが今の私の評価です。
参照＞ブラウザ上とDeveloperコンソール上でのJS速度比較
　　　http://qiita.com/items/cf8d031f2d234aff73c9

-----

forEach と for と forin の速度比較は以前に forEach が爆速だと確認済みだったのだけれど、念のために、もう一度確認してみました。

下記のようなコードの場合は、やはり、forEachがダントツに早いです。

まぁ、当然ながら下記のようなコードでは、事前に使える配列が無いとforeEachやforは使えないということはあります。

P.S.もちろん、ベンチはあくまでベンチということで。

追記：forEachよりforが早いというベンチを教えてもらいました。
http://jsperf.com/lo-dash-each-vs-native-foreach/3
コールバックで計測していることと、ライブラリを同時にテストしてるようですが、この手のコールバック処理するケースもあとで別に試してみようと思います（ → http://qiita.com/items/c07329ec9500094e0ad7 ）。

##テストコード

これをコンソールなどへコピペで打ち込むと簡単にテストできます。
3回目以降は、念のために、テストの順番を少し変えてみています。

```javascript
var d = [];
var loopLen = 10000;
//配列を作る d[0,1,2,3,...loopLen]
for (var i = 0; i <= loopLen ; i++) d.push(i);
var dlen = d.length;

console.log('===== テスト1回目 =====');

//for
console.time('for');
for (var i = 0; i < dlen; i++) {
    if (i === loopLen ) {
        console.timeEnd('for');
    }
}
//forin
console.time('forin');
for (var i in d) {
    if (d[i] === loopLen ) {
        console.timeEnd('forin');
    }
}
//forEach
console.time('forEach');
d.forEach(function (x, i) {
    if (i === loopLen ) {
        console.timeEnd('forEach');;
    }
});

console.log('===== テスト2回目 =====');

//for
console.time('for');
for (var i = 0; i < dlen; i++) {
    if (i === loopLen ) {
        console.timeEnd('for');
    }
}
//forin
console.time('forin');
for (var i in d) {
    if (d[i] === loopLen ) {
        console.timeEnd('forin');
    }
}
//forEach
console.time('forEach');
d.forEach(function (x, i) {
    if (i === loopLen ) {
        console.timeEnd('forEach');;
    }

});

console.log('===== テスト3回目 =====');

//forEach
console.time('forEach');
d.forEach(function (x, i) {
    if (i === loopLen ) {
        console.timeEnd('forEach');;
    }
});
//for
console.time('for');
for (var i = 0; i < dlen; i++) {
    if (i === loopLen ) {
        console.timeEnd('for');
    }
}
//forin
console.time('forin');
for (var i in d) {
    if (d[i] === loopLen ) {
        console.timeEnd('forin');
    }
}

console.log('===== テスト4回目 =====');

//for
console.time('for');
for (var i = 0; i < dlen; i++) {
    if (i === loopLen ) {
        console.timeEnd('for');
    }
}
//forEach
console.time('forEach');
d.forEach(function (x, i) {
    if (i === loopLen ) {
        console.timeEnd('forEach');;
    }
});
//forin
console.time('forin');
for (var i in d) {
    if (d[i] === loopLen ) {
        console.timeEnd('forin');
    }
}

```

##結果

```
Chrome 25.0.1364.172 m
--------------------------
===== テスト1回目 =====
for: 20.000ms
forin: 15.000ms
forEach: 5.000ms
===== テスト2回目 =====
for: 20.000ms
forin: 15.000ms
forEach: 5.000ms
===== テスト3回目 =====
forEach: 6.000ms
for: 20.000ms
forin: 16.000ms
===== テスト4回目 =====
for: 20.000ms
forEach: 5.000ms
forin: 15.000ms

Firefox 19.0.2
--------------------------
[14:44:02.364] ===== テスト1回目 =====
[14:44:02.364] for: タイマー開始
[14:44:02.369] for: 5ms
[14:44:02.369] forin: タイマー開始
[14:44:02.375] forin: 6ms
[14:44:02.375] forEach: タイマー開始
[14:44:02.377] forEach: 2ms
[14:44:02.377] ===== テスト2回目 =====
[14:44:02.377] for: タイマー開始
[14:44:02.382] for: 5ms
[14:44:02.382] forin: タイマー開始
[14:44:02.388] forin: 6ms
[14:44:02.388] forEach: タイマー開始
[14:44:02.391] forEach: 3ms
[14:44:02.391] ===== テスト3回目 =====
[14:44:02.391] forEach: タイマー開始
[14:44:02.393] forEach: 2ms
[14:44:02.393] for: タイマー開始
[14:44:02.398] for: 5ms
[14:44:02.398] forin: タイマー開始
[14:44:02.403] forin: 5ms
[14:44:02.403] ===== テスト4回目 =====
[14:44:02.403] for: タイマー開始
[14:44:02.408] for: 5ms
[14:44:02.408] forEach: タイマー開始
[14:44:02.410] forEach: 2ms
[14:44:02.410] forin: タイマー開始
[14:44:02.416] forin: 6ms
```

##別のパターン

参考までに、上記ではブロック内で配列操作をしていませんので、一般的ではなさすぎるということで、a[i] = d[i] * 2;というコードを挿入したケースです。

まぁ、結果はほぼ同じで forEach が早いです。

```
var a = [];
var d = [];
var loopLen = 10000;
//配列を作る d[0,1,2,3,...loopLen]
for (var i = 0; i <= loopLen ; i++) d.push(i);
var dlen = d.length;

console.log('===== テスト1回目 =====');

//for
console.time('for');
for (var i = 0; i < dlen; i++) {
    a[i] = d[i] * 2;
    if (i === loopLen ) {
        console.timeEnd('for');
    }
}
console.log(a);var a = [];

//forin
console.time('forin');
for (var i in d) {
    a[i] = d[i] * 2;
    if (d[i] === loopLen ) {
        console.timeEnd('forin');
    }
}
console.log(a);var a = [];
//forEach
console.time('forEach');
d.forEach(function (x, i) {
    a[i] = d[i] * 2;
    if (i === loopLen ) {
        console.timeEnd('forEach');;
    }
});
console.log(a);var a = [];
```

##結果

```
Chrome 25.0.1364.172 m
--------------------------
===== テスト1回目 =====
for: 35.000ms
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198…]
forin: 33.000ms
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198…]
forEach: 11.000ms
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198…]

Firefox 19.0.2
--------------------------
[14:54:51.071] ===== テスト1回目 =====
[14:54:51.071] for: タイマー開始
[14:54:51.079] for: 8ms
[14:54:51.080] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, [...]
[14:54:51.080] forin: タイマー開始
[14:54:51.091] forin: 11ms
[14:54:51.091] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, [...]
[14:54:51.091] forEach: タイマー開始
[14:54:51.096] forEach: 5ms
[14:54:51.096] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, [...]
```