使用纯javascript通过className来获取元素 (ge

系统 2424 0

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’s className 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.

  1. Supply a class name as a string.
  2. (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.
  3. (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/

使用纯javascript通过className来获取元素 (getElementsByClassName Speed Comparison)

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元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论