Hatena::Groupptech

ぷちてく RSSフィード

Archive
 
ProfileProfile

2012-05-21

配列ライクなオブジェクトをforEachするときのイディオム

07:31

どーもこんちわ。ベタ線なんだけど比較書いてあるところが探せなかった。やり方はわかるけど、どれがどういいのかよくわからないパターン

よくさわるところだとHTMLCollectionとかNodeListとかargumentsとか。いわゆる 「lengthもってるけど配列じゃない系オブジェクト」or「Array-like Object」

パフォーマンス気にしないでforEachする時に、どうかくか っていう。

Environment

FireFoxChrome
12.019.0.1084.46 m

Array.prototype.forEach.call

これよく使ってる。単にforEachthisをかえるやつ

Array.prototype.forEach.call(document.querySelectorAll('span'), function(node) {
    console.log(node);
});

やりたいのはforEachだから素直にみえる気がする。

Array.prototype.slice.call

これ結構他のひとのUserScriptとかで見る。sliceで一旦配列に変換したうえでforEach呼ぶ

Array.prototype.slice.call(document.querySelectorAll('span')).forEach(function(node) {
    console.log(node);
});

引数少ない、とかパフォーマンスいいとかなのかな。ちょっとわかりづらい気がするんだけど人によりけりかも

配列メソッド呼ぶ

Array.prototypeが長いからショートコーディングできる、とかがいいとこなのかな。コンソールとかでたまに打つけどコードには入れない。こういうの

[].forEach.call(document.querySelectorAll('span'), function(node) {
    console.log(node);
});

なんとなく配列無駄に生成してる感があってつかわない。イメージだけど

Array generics

Firefox、というか Javascript 1.6 っていった方がいいのかな。Arrayの汎用化ってやつがあるから、prototypeすっ飛ばしてこうかける。callしてやる必要もない

Array.forEach(document.querySelectorAll('span'), function(node) {
    console.log(node);
});

当たり前だろと思ってる人はたぶんFirefox使いのひととかで、Chromeでこれやるとぶっ飛ぶよ

TypeError: Object function Array() { [native code] } has no method 'forEach'

実装まち、なのかなー。正確には Array and String generics で、Stringも拡張されてる

MDN的な「こう書け」

コアJavaScriptのところに載ってる。ちなみに日本語版はない。MDNは日本語のやつ色々いけてないから基本的に en 見てわかんなかったら日本語あるかな、くらいがいいとおもう

function alertArguments() {
   Array.forEach(arguments, function(item) {
     alert(item);
   });
 }
Array.prototype.forEach.call(arguments, function(item) {
   alert(item);
 });
Working with Array-like objects - Predefined Core Objects - MDN

まーArray.forEachすればよくて、無いならArray.prototype.forEach.callってかんじ。

小話

イディオムの話はおわりで、ここから関係するやつ系

ECMAScriptの実装対応表

http://kangax.github.com/ においてあるやつ、各ブラウザとバージョンで組み込みメソッドの実装があるかわかってすごいべんりっぽい。kangax (Juriy Zaytsev)++!

ECMAScriptの規格自体は詳しくないからよくわかりますん。ごめんちゃい

HTMLCollection

Chromeの場合getElementsByTagNameNodeList返すけど、FirefoxHTMLCollection返ってくる

document.getElementsByTagName('span') instanceof HTMLCollection;
// Firefox => true 
document.getElementsByTagName('span') instanceof NodeList;
// Chrome => true
どうして?

HTMLCollectionだとW3Cの勧告*1とちがうんだけど、MDNにその辺の話が各ブラウザ含めて詳しく書いてある

Note: While the W3C specification says elements is a NodeList, this method returns a HTMLCollection both in Gecko and Internet Explorer. Opera returns a NodeList, but with a namedItem method implemented, which makes it similar to a HTMLCollection. As of January 2012, only in WebKit browsers is the returned value a pure NodeList. See bug 14869 for details.

Document.getElementsByTagName() - Web APIs | MDN

ちなみにMDN日本語版だとNodeListが返ってくるとしか書いてなくて、上のNoteがない。

削られてるのか、翻訳後に追加されたのかわかんないけど混乱するとおもう。jaひどす

MDN jaひどすな例かも?

前に読んだエントリでスターポチったんだけど、 id:superbrothers さんはこのときドキュメントのせいではまったのかも。

なんか斜め上なコメントがついててうけた。JavaScript触りたてくらいに読んですごい助かったからトラバ。 superbrothers++!

NodeList

スタティックDOMだとかはおいといてSelectorsAPIでよく取ってくる

document.querySelectorAll('span') instanceof NodeList;
// => true

SelectorsAPIべんりだよね。すき

たまには

こういうコード系Blogのマネごとみたいなのも いいかもと思ってかいた。ハードボイルド

イディオム系で何選択したらいいかわかんないの他にも色々あるから、たまにかいてこう。いいJavaScript本にもあんまり書いてない気がするやつとか。

しーゆー

*1:すっごい重いよ!W3Cのページって縦に長すぎだとおもう


Copylight (c) noromanba 2012-2017