こんばんは、martinです。ソーシャルブックマークへのリンクアイコンを各記事に付けるようにしました。近々配布予定の最新版に採用してます。またJavaScript関連の話をば。
愛用しているタブブラウザFirefoxの現行バージョンは2ですが、バージョン3からはネイティブでdocument.getElementsByClassNameがサポートされる ようです。現時点でこのメソッドをサポートしている主要なブラウザは存在しないので、document.getElementsByClassNameGでググれば分かるように、皆さん、色んなgetElementsByClassNameを書いています。ppBlogのJavaScriptのライブラリlib.jsでも、この関数(getByClass)は多用しているのですが、この関数は、ページ内のオブジェクトを逐一調べていくループ作業を伴うので、一般的に言って動作に時間がかかります。
JavaScript使いの間では、常識かと思いますが、この手の操作で一番スピードが速いのは、XPathGを利用するやり方です。jQueryGで有名なJohn Resig氏のブログに、この手の関数のスピード比較記事があります。
→http://ejohn.org/blog/getelementsbyclassname-speed-comparison/
ネイティブサポートのFirefox3が無茶苦茶速いのは当然として、XPathもDOMを解析していく手法よりはずっと高速なのが分かります。IE6,7を除くモダンなブラウザは、このXPathをサポートしているので、ppBlogでもXPathを使うようにしました。以下のような感じです。
document.getElementsByClassName(className, pElement, tagName){ var d = document, nodes = [], item; try { // XPathをサポートしているならこれを使う var xp = d.evaluate( './/'+(tagName || '*')+'[contains(concat(" ", @class, " "), " '+className+' ")]', (pElement || d), null, XPathResult.ANY_TYPE, null ); for (item = xp.iterateNext(); item; item = xp.iterateNext()){ nodes.push(item); } } catch(e){ // そうでなければ地道にDOM解析 var cls, items = (pElement || d).getElementsByTagName((tagName || '*')); for(var i = 0, l = items.length; i < l; i++){ item = items[i]; if(item.className){ cls = item.className.split(/¥s+/); for(var j = 0, k = cls.length; j < k; j++){ if(cls[j]==className){ nodes[nodes.length] = item; break; } } } } } return nodes.length > 0 ? nodes : null; }
John Resig氏のブログにあるのと同じ実験 をしてみましたが(パクっただけ)、彼のサイトにある、Prototype.jsのXPathを使ったもの(xpath.html
)と同等か少し速いくらいですね。
当然ながら、XPathをサポートしていないIE6,7は、通常通りDOM解析をするアプローチしかないです。こちらの計測では、XPathを利用するより5倍ほど遅いです。
ちなみに、1つ前のエントリで紹介したphotoeffect.jsも、この関数を使用しているので更新しました。ついでに添付しておきますね。このphotoeffect.jsは、単体で動くので、ppBlog以外の各種ブログでも外部ファイルとして呼び込むだけで簡単に使えます。要望があれば、詳しいクラス指定などの解説書きますんで、その時はたずねて下さい。

Comments