You Don't Need jQuery とは言うものの
You Don't Need jQuery をみて気になるのが、forEachの書き方。querySelectorAllで帰ってくるNodeListは配列ではなくオブジェクトなので、JavaScriptのforEachが使えない。
そこで登場するのが
Array.prototype.slice.call
これで、配列っぽいオブジェクトが配列扱いになるらしい。配列っぽいオブジェクトって何?
試しに文字列をいれてみる
Array.prototype.slice.call("ab")
> ["a", "b"]
となる。ただ素のオブジェクトを入れても
Array.prototype.slice.call({0:"value1",1:"value2"})
> []
にしかならない。
試しに、lengthをもった、数字がキーのオブジェクトを作って、それを配列化してみよう
Array.prototype.slice.call({0:"value1",1:"value2",length:2})
> ["value1", "value2"]
期待通り。どうも、Length をみて、[0][1]と切り出しているだけっぽい。Lenghと添字アクセスが可能だから文字列が配列に変換できたっぽいね。ということで、手作業で配列っぽいオブジェクトは作れる。
本題のNodeListのforEach。
「ページの中のアンカーのhrefを全部出力するってワンライナー」はこうかける
Array.prototype.slice.call(document.querySelectorAll("a")).forEach( function(e){ console.log(e.href)})
長い。メソッド深すぎ、タイプ多すぎ。読みづらい。
配列に変換したいのではなく、foreEachを使いたいだけなんだから、一足飛びにforEachをcallしてみよう。foEachをCallすると、第一引数にNodeListを直接ぶち込んで、第二引数でcallbackを指定できる。
Array.prototype.forEach.call(document.querySelectorAll("a"), function(e){ console.log(e.href)})
ちょっと短くなった。sliceって単語が出てこないだけ見通しがいい。
いまどきのブラウザは、Arrow Function もサポートし始めているから、スペルミスの多いfunction は省略しちゃおう。
Array.prototype.forEach.call(document.querySelectorAll("a"), e => console.log(e.href))
さらに短くなった。Array.prototypeも面倒だ。prototypeが打ちづらい。
[].forEach.call(document.querySelectorAll("a"), e => console.log(e.href))
さらに短くなった。
ES6になると、配列化とmapの両方をやってくれる、Array.fromというメソッドがある。まぁ親切。これ最強。
Array.from(document.querySelectorAll("a"), e => console.log(e.href))
手元の Chromeバージョン 50.0.2661.94 (64-bit)では動いている。
ちなみに第二引数で処理されるのはforEachではなくmapなので、returnすれば、配列に変換できる。
Array.from(document.querySelectorAll("a"), e => {return e.href;})
「ページ内のアンカーのhrefを配列にして、それを改行でjoinして出力」くらいが事務用途で便利。
(コンソールからコピペした時に余計なものがついてこない)
console.log(Array.from(document.querySelectorAll("a"), e => {return e.href;}).join("\n"))