Mark Finkle suggested that I do some speed testing, now that a native implementation of getElementsByClassName has landed in the Mozilla trunk (destined for Firefox 3).
?
So I went around and dug up all of the different, existing, implementations that I could find. Currently, implementations fall into one of three categories (with some straddling more than one):
?
-
Pure DOM
This usually involves a calls to.getElementsByClassName("*")
and traversing through all matched elements, analyzing each element’sclassName
attribute along the way. Generally, the fastest method is to use a pre-compiled RegExp to test the value of the className attribute. -
DOM Tree Walker
Is a less-popular means of traversing DOM documents by setting some simple parameters, as specified by the DOM Level 2 Spec. For example, you could traverse through all text nodes in a document (something that you can’t easily do in any other way). -
XPath
The most recent technique, to be popularized, was the use of XPath to find elements by classname. The implementation is generally simple: Building a single expressions and letting the XPath engine traverse through the document, finding all the relevant elements.
I’ve chosen some implementations that were representative of each of these techniques.
?
Tree Walker
An implementation using the DOM Level 2 Tree Walker methods. Builds a generic filter function and traverses through all elements.
document.getElementsByClass = function(needle) { function acceptNode(node) { if (node.hasAttribute("class")) { var c = " " + node.className + " "; if (c.indexOf(" " + needle + " ") != -1) return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_SKIP; } var treeWalker = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, acceptNode, true); var outArray = new Array(); if (treeWalker) { var node = treeWalker.nextNode(); while (node) { outArray.push(node); node = treeWalker.nextNode(); } } return outArray; }
?
The Ultimate getElementsByClassName
Uses a pure DOM implementation, tries to make some optimizations for Internet Explorer.
function getElementsByClassName(oElm, strTagName, strClassName){ var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName); var arrReturnElements = new Array(); strClassName = strClassName.replace(/\-/g, "\\-"); var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)"); var oElement; for(var i=0; i<arrElements.length; i++){ oElement = arrElements[i]; if(oRegExp.test(oElement.className)){ arrReturnElements.push(oElement); } } return (arrReturnElements) }
?最新更新請點擊 這里 ,或者看附件。
?
Dustin Diaz’s getElementsByClass
A pure DOM implementation, caches the regexp, and is generally quite simple and easy to use.
?
It's simple. It works just how you think getElementsByClass would work, except better.
- Supply a class name as a string.
- (optional) Supply a node. This can be obtained by getElementById , or simply by just throwing in " document " (it will be document if don't supply a node)). It's mainly useful if you know your parent and you don't want to loop through the entire D.O.M.
- (optional) Limit your results by adding a tagName . Very useful when you're toggling checkboxes and etcetera. You could just supply " input ". Or, if you're like me, and you said Good Bye to IE5 , you can use the "*" asterisk as a catch-all (meaning 'any element).
function getElementsByClass(searchClass,node,tag) { var classElements = new Array(); if ( node == null ) node = document; if ( tag == null ) tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); for (i = 0, j = 0; i < elsLen; i++) { if ( pattern.test(els[i].className) ) { classElements[j] = els[i]; j++; } } return classElements; }
?
Prototype 1.5.0 (XPath)
Mixes an XPath and DOM implementation; using XPath wherever possible.
document.getElementsByClassName = function(className, parentElement) { if (Prototype.BrowserFeatures.XPath) { var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; return document._getElementsByXPath(q, parentElement); } else { var children = ($(parentElement) || document.body).getElementsByTagName('*'); var elements = [], child; for (var i = 0, length = children.length; i < length; i++) { child = children[i]; if (Element.hasClassName(child, className)) elements.push(Element.extend(child)); } return elements; } };
?
Native, Firefox 3
A native implementation, written in C++; is a part of the current CVS version of Firefox, will be included in Firefox 3.
document.getElementsByClassName
?
The Speed Results
For the speed tests I copied the Yahoo homepage into a single HTML file and used that as the test bed. They make good use of class names (both single and multiple) and is a considerably large file with lots of elements to consider.
?
You can find the test files, for each of the implementations, here:
http://ejohn.org/apps/classname/
Note: “XPath” is just Prototype’s implementation.
?
From these figures we can see that the native implementation of getElementsByClassName, in Firefox 3, is a full 8x faster than the XPath implementation. Additionally, it’s a stunning 77x faster than the fastest DOM implementation.
Note: These numbers have been revised from what was originally posted as the lazy-loading nature of
document.getElementsByClassName
wasn’t taken into account. The resulting arrays are completely looped-through now, making sure that all elements are accounted for.
Currently, Prototype has the best general-use implementation: Use XPath selectors wherever possible, fall back to fast DOM parsing.
?
Interestingly, only Prototype actually tries to implement the
document.getElementsByClassName
interface (all others do one-off names). However, Prototype doesn’t check to see if the
document.getElementsByClassName
property already exists, and completely overwrites the, incredibly fast, native implementation that Firefox 3 provides (oops!).
?
In all, the results are quite astounding. The native implementation is absolutely much faster than anything I could’ve imagined. It completely decimates all the other pieces of code. I can’t wait until this hits the general public – users will, absolutely, feel a significant increase in speed.
?
來源:
http://ejohn.org/blog/getelementsbyclassname-speed-comparison/
參考: http://stackoverflow.com/questions/3808808/how-to-get-element-by-class-in-javascript
function replaceContentInContainer(matchClass,content) { var elems = document.getElementsByTagName('*'), i; for (i in elems) { if((' ' + elems[i].className + ' ').indexOf(' ' + matchClass + ' ') > -1) { elems[i].innerHTML = content; } } }
?
我的實例:
<script type="text/javascript"> function getElementsByClass(searchClass,node,tag) { var classElements = new Array(); if ( node == null ) node = document; if ( tag == null ) tag = "*"; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); for (i = 0, j = 0; i < elsLen; i++) { if ( pattern.test(els[i].className) ) { classElements[j] = els[i]; j++; } } return classElements; } var gd = getElementsByClass("common_li",document.getElementById("show_thumb_photo"),"li"); alert(gd[0].innerHTML); </script>
?
使用純javascript通過className來獲取元素 (getElementsByClassName Speed Comparison)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
