querySelector getElementsByTagName区别

昨天miller推荐了一篇 文章,说明为何document.getElementsByTagName比querySelectorAll快。
先简要的说一下文章里的要点,了解这个,这对于我们写代码有直接的好处。
  • 引用
    document.getElementsNodeList and NamedNodeMap objects in the DOM are live; that is, changes to the underlying document structure are reflected in all relevant NodeList and NamedNodeMap objects.
    (NodeList和NamedNodeMap对象在DOM里是动态的,这意味着改变document结构将会影响NodeList和NamedNodeMap对象),webkit代码在这里,假装看了下,基础实现是一开始创建cache,当改变时,把cache的list也更改,即每次我们拿到的都是这个cache,我们把此可以理解成索引。
  • W3C定义document.querySelectorAll是静态的(static)对象
    引用
    The NodeList object returned by the querySelectorAll() method must be static, not live ([DOM-LEVEL-3-CORE], section 1.1.1))
    webkit内核里用StaticNodeList表示。代码在这里(要FQ)
证明

在上文写了两串代码,为了方便看效果,我修改了下代码,来看看动态的节点与静态节点有什么区别。
<div></div>
<script>
var divs, i=0;
//divs = = document.querySelectorAll("div"); //可以把这句去除注释,把下句加上注释
divs = document.getElementsByTagName('div');
setInterval(function() {
  if (i < divs.length){
    var d = document.createElement("div");
    d.innerHTML = Math.random();
    document.body.appendChild(d);
    i++;
  }
},50);
</script>
这是测试一下是否为索引。
还有一个简单的例子。
<div></div>
<script>
divs = document.getElementsByTagName('div');
setTimeout(function(){
alert(divs.length);
},0);
divs[0].parentNode.removeChild(divs[0]);
</script>

月影 写了两行代码更能说明效果。
alert(document.getElementsByTagName('div')===document.getElementsByTagName('div')); //true
alert(document.querySelectorAll('div')===document.querySelectorAll('div')); //false
true意味着他们拿到的同是cache引用。
static每次返回都是不一样的Object。

实际应用

querySelectorAll在这里不说细说查找方式了,之前我已经有文章说过。
现在看实际应用我们用getElementsByTagName有几种方式
  • document.getElementsByTagName
  • document.documentElement.getElementsByTagName
  • HTMLElement.getElementsByTagName
初看,第一种与第二种很相似,没有什么区别么?看下面代码(IE下看效果)。
<script type="text/javascript">//<![CDATA[
//by wc
void function () {
  var i = 0, l = 5000, divs = [];
  for (; i < l ; ++ i) {
    divs.push('<div id="test-' + i + '">');
    //divs.push('<div id="test-' + i + '"></div>');
  }
  var temp = new Array(l + 1).join('</div>');
  divs.push(temp);
  
  document.write('<div id="tester">' + divs.join('\n') + '</div>');
  //document.write('<div id="tester">' + divs.join('\n') + temp.replace('<', '</') + '</div>');
}();

d = new Date;
document.getElementsByTagName('div');
alert(new Date-d);

d = new Date;
document.documentElement.getElementsByTagName('div');
alert(new Date-d);
//]]></script>

IE下的测试结论

好奇 测试得出(由效率时间上可以看到):
  • document.getElementsByTagName => IE被索引的速度
  • document.documentElement.getElementsByTagName =>IE不被索引的速度
  • element.getElementsByTagName =>IE不被索引的速度
总结:除document根结点IE效率被索引,其他的地方看不出被索引的速度。(包括ie,6,7,8),所以查找节点时需要注意下,例如在document.body上查找时,可以扩大到document上查到tagName节点

另外 miller写了个case。 http://jsperf.com/getelementsbytagname
 
 
http://www.never-online.net/blog/article.asp?id=301

你可能感兴趣的:(querySelector getElementsByTagName区别)