2017年はforEach元年

# いまさらforEach？

5000兆人のJavaScriptファンの皆様こんばんわ。
[JavaScript Advent Calendar 2017](https://qiita.com/advent-calendar/2017/javascript) 22日目の記事です。
2017年と言えば、forEach元年。
誰が何と言おうと、forEach元年です。
＼おめでとう／


茶番はここまでにして、forEachとはなんぞやから書いていきたいと思います。


# forEachとは

[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
まずは、MDNのドキュメントに目を通しましょう。
配列操作をいい感じにしてくれる機能の事です。ES5で追加された機能ですね。


## ブラウザの対応状況

- Chrome
- Edge
- Firefox
- IE9（？！）
- Opera
- Safari

はい。
大抵のブラウザは、forEachに対応しています。
あの悪名高きIEも、9以降からならforEach使えるんですねー。
これは余談なのですが、最近はIE案件を受けることも減ってきていて、いい加減古い書き方を捨てても良いかなーと思うようになってきました。
ってか、最近は古い書き方を捨てて、新しい書き方をどんどん取り入れています。
凄い快適です。


## ここまでは前座

長い前振りになりましたが、ここまでは前座です。
ここから、forEachを使う前から、forEachを使った良くある書き方を見つつ、最新版ではどうなっていくのか、ご覧ください。


# <ruby><rb>歴史的</rb><rt>レガシィ</rt></ruby>コードで辿るforEach

## 原始時代

```javascript:primitive-age.js
var elements = document.getElementsByTagName("a");
for( var i=0; i<elements.length;i++ ){
    var element = elements[i];
    element.className += " link";
}
```

このコードに意味があるかどうかはともかく、aタグ全てにlinkクラスをくっつけるという非常にシンプルなコードです。
誰が読んでも分かりやすいというメリットがあるのですが、書き方が古すぎますね。
呼び出しているAPIが古いですし、classNameにアクセスしている当たりアレですし、forループの書き方もとても泥臭い。
とても原始的な書き方なのですが、誰でも、つまり**死ぬほど古いブラウザ**でも理解できるコードという事で、一定の需要はあります。


## 石器時代

```javascript:stone-age.js
var elements = document.querySelectorAll("a");
for( var i=0,iz = elements.length; i<iz;i++ ){
    var element = elements[i];
    element.className += " link";
}
```

少しだけ書き方が変わっています。
まず、APIとして、querySelectorAllを使うようになりました。
[https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)
JavaScriptをある程度かじっている人なら、このAPI使ってHTMLの要素を取得するのは常識ですよね。
余程変なことをしていなければ、IE8でもサポートされているAPIですし、これを使わない手はありません。

forループの書き方もちょっとだけ精錬されています。
個人的には[uupaa式](https://github.com/uupaa)と勝手に呼んでいるのですが、izという変数を使うことによる若干の高速化が図られています。
とても素敵な書き方ですねっ。
もし、原始時代のコードをメンテするという地獄に突き落とされた場合、この石器時代のコードは多少なりとも抗えますので、すこしでも時代を進めることをお薦めします。


## 中世

```javascript:middle-age.js
var elements = document.querySelectorAll("a");
var addLinkClass = function( element, index, array ){
    element.className += " link";
};
Array.prototype.forEach.call( elements, addLinkClass );
```

さあ、ようやく中世に到達しました。
ここでforEachの登場です。
良い書き方ですねー、実にJavaScriptらしい書き方で、僕は好きです。
Arrayオブジェクトのprototypeをcallするというテクニカルな書き方です。
JavaScriptのprototypeベースでのコーディングの面白い所であり、難しい所でもあります。
中世と言いながら、案外ハードルの高い書き方ですが、まあ、こういうテクニックがあるよーって事で、ご理解頂ければと思います。

さて、疑問に思う方が多いかもしれませんが、querySelectorAllで取得したのは配列では無いのかという事です。
elements.lengthみたいにアクセス出来るので、配列の仲間かなーと思いきや、コイツは[NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)という全く別のオブジェクトです。


**なので、forEachが使えません**


というのが、中世までの常識でした。


## 近代
```javascript:modern-times.js
var elements = document.querySelectorAll("a");
var addLinkClass = function( element, index, array ){
    element.classList.add("link");
};
elements.forEach(addLinkClass);
```

はい！近代に到達し、なんと、**NodeListオブジェクトがforEachをサポートするようになりました**、拍手ー！
パチパチパチ～

ここが、タイトルに繋がるのですが、多くのブラウザがこの**NodeListがforEach対応したのが、2017年**なのですっ！
タイトル回収できて良かったです。←なげーよ

[https://developer.mozilla.org/ja/docs/Web/API/NodeList/forEach](https://developer.mozilla.org/ja/docs/Web/API/NodeList/forEach)
ここを参考にすれば分かりますが、Edge16でサポートされた事により、ほぼほぼメジャーなブラウザでは、NodeListでforEeachを使うことが可能になっています。
Wikipediaベースになりますが、各ブラウザのリリース履歴を参照すると、サポート時期を推定できます。

- Chromeは、2016/5/25
- Operaは、2016/6/8
- Edgeは、2017/9/26
- Safariは、2016/9/20
- Firefoxは、2016/6/8


去年の5月頃から次々と実装されて、Edgeがつい最近サポートしたという形ですね。
なお、**IEでは当然のように動かない模様**

参考

- [https://en.wikipedia.org/wiki/Google_Chrome_version_history](https://en.wikipedia.org/wiki/Google_Chrome_version_history)
- [https://en.wikipedia.org/wiki/History_of_the_Opera_web_browser](https://en.wikipedia.org/wiki/History_of_the_Opera_web_browser)
- [https://en.wikipedia.org/wiki/Microsoft_Edge#Release_history](https://en.wikipedia.org/wiki/Microsoft_Edge#Release_history)
- [https://en.wikipedia.org/wiki/Safari_version_history](https://en.wikipedia.org/wiki/Safari_version_history)
- [https://en.wikipedia.org/wiki/Firefox_version_history](https://en.wikipedia.org/wiki/Firefox_version_history)



他にも、Android Browserが対応していない事に目眩と頭痛と吐き気を感じますが、いずれは対応していく事でしょう。


しれっと、[classList](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)を使っていますが、これはとても便利なAPIなので、ぜひとも覚えていってください。
IE10以降のブラウザなら、大体サポートしています。


## 現代
```javascript:present-day.js
document.querySelectorAll("a").forEach(element => {
   element.classList.add("link");
});
```

現代では、アロー関数が使えるようになっています。
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

もう既に常識かもしれませんが、大体のブラウザでもアロー関数は有効です。
アロー関数を使うと、thisを直感的に書けるようになるので、とてもコーディングが楽になります。

```javascript:old-technic.js
var _selft = this;
```

みたいな古いノウハウを使わなくても良くなるので、アロー関数はどんどん採用して欲しいものです。


という事で、**短いコードで振り返るJavaScriptの書き方遷移**でした（タイトル変わってるがな）


# 最後に

最後になりますが、こちらに記載したコードは全て[Vivaldi](https://vivaldi.com/?lang=ja_JP)で動作確認しています。
Vivaldiでも最新のコードをしれっと動かせたのが楽しかったです。