昨天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