■
- New in JavaScript 1.7 - MDC
- あれれ。Generatorが使えるようになってるじゃあないか。それならPythonみたいにNodeListを扱えるかと思って、次を試してみた。
NodeList.prototype.items = function(){ for (let i=0, len=this.length; i<len; i++) { yield this.item(i); } }; var nl = document.getElementsByTagName("P"); for each(let elm in nl.items()) { alert(elm.textContent); }
- これならfor eachでNodeListを扱うときに余計な判別式を使わなくてすむ。と思いきや何故かnl.itemsがundefined。nl instanceof NodeListはtrueなのにね。まあ実装方法はこうでなくてもいいわけで、とりあえずGeneratorの動作を確認すべく再試行した。
var nl = document.getElementsByTagName("P"); for each(let elm in NodeList.prototype.items.apply(nl)) { alert(elm.textContent); }
- ちなみにJavascript1.7のにゅーフィーチャー「destructuring assignment」を使うとさらにPythonicなスクリプトが書けるよ。
var nl = document.getElementsByTagName("P"); for each(let {textContent: c, attributes: a} in NodeList.prototype.items.apply(nl)) { let s = ""; for each(let {name: n, value: v} in NodeList.prototype.items.apply(a)) { s += n + " = " + v + "\n"; } s += c; alert(s); }
- prototypeチェインが繋がらないのが謎だけど、チェインに拘らなければ別に気にならない。そもそも上の例ではprototypeチェインでitemsジェネレータを繋ごうとすると、継承関係のないNamedNodeMapとNodeListそれぞれに同じことをしなければならない(まあできないんだけど)。だったらクラスメソッドにでもしておいた方が良いのかも。
- 4.4. Doing something for every HTML element [Dive Into Greasemonkey]
- NodeListは「生きて」いるのでlengthプロパティはgetterを呼ぶ。これではforループで毎回呼び出すことになるだろう。しかもgetElementsByTagName("*")でその回数は膨大。今まではlengthプロパティの「値」を参照する代案を提示してきたが、Greasemonkey scriptということでJavascript1.6が使える前提で例を。
-
var allElements, thisElement; allElements = document.getElementsByTagName('*'); for each (thisElement in allElements) { if (!(thisElement instanceof Element)) continue; // do something with thisElement; }
- 参照:Core JavaScript 1.5 Reference - MDC