日期:2014-05-16  浏览次数:20546 次

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

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