24
14

More than 5 years have passed since last update.

2017年はforEach元年

Last updated at Posted at 2017-12-21

いまさらforEach?

5000兆人のJavaScriptファンの皆様こんばんわ。
JavaScript Advent Calendar 2017 22日目の記事です。
2017年と言えば、forEach元年。
誰が何と言おうと、forEach元年です。
\おめでとう/

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

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を使った良くある書き方を見つつ、最新版ではどうなっていくのか、ご覧ください。

歴史的レガシィコードで辿るforEach

原始時代

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ループの書き方もとても泥臭い。
とても原始的な書き方なのですが、誰でも、つまり死ぬほど古いブラウザでも理解できるコードという事で、一定の需要はあります。

石器時代

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
JavaScriptをある程度かじっている人なら、このAPI使ってHTMLの要素を取得するのは常識ですよね。
余程変なことをしていなければ、IE8でもサポートされているAPIですし、これを使わない手はありません。

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

中世

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という全く別のオブジェクトです。

なので、forEachが使えません

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

近代

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
ここを参考にすれば分かりますが、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では当然のように動かない模様

参考

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

しれっと、classListを使っていますが、これはとても便利なAPIなので、ぜひとも覚えていってください。
IE10以降のブラウザなら、大体サポートしています。

現代

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

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

old-technic.js
var _selft = this;

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

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

最後に

最後になりますが、こちらに記載したコードは全てVivaldiで動作確認しています。
Vivaldiでも最新のコードをしれっと動かせたのが楽しかったです。

24
14
1

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
24
14