论坛首页 Web前端技术论坛

深入讨论document.getElementById

浏览 11873 次
精华帖 (1) :: 良好帖 (7) :: 新手帖 (7) :: 隐藏帖 (1)
作者 正文
   发表时间:2009-08-19   最后修改:2009-08-19
前天在http://www.iteye.com/topic/450250这篇文章的回帖中跟zbm2001起了一点小小的争吵,回帖我已经主动和谐.

zbm2001兄认为如果在循环中,用引用来取一个dom节点比用document.getElementById来取高效的多,当然相信这也代表大部分人的观点.
我说的是这2种方法的效率差不多,因为大部分浏览器对document.getElementById做了优化.况且我不喜欢管理多余的局部变量.

证明我的观点之前先回忆一句话,动态增加或删除dom节点的性能比较低,因为会导致节点树的索引重排,听起来跟数组的插入和删除一样.那么我相信这些索引不是排队去打酱油的,它们也保存在一个链表中,留给document.getElementById和document.getElementsByTagName的时候用.

PS: document.getElementsByName抗议了,谁叫你出镜率低呢.


ecma里无解.所以做了一些测试,分别在几百个节点的新浪首页和十多个节点的百度首页做了测试.等页面加载完之后分别执行下面这几段代码.测试5次取平均值.单位ms.测试document.getElementsByTagName的结论跟document.getElementById的差不多,所以这里只讨论后者.

1 : 用引用来取
   var a = document.getElementById('PartA');
	
	var d = new Date;
	
	for (var i = 0; i < 10000; i++){
		a;
	}
	alert (new Date - d);	


                 
结果 :      百度      新浪
        IE6 : 40       500
        IE7 : 1        46
        FF2 : 1        1
        CHR : 1        1

2: 用document.getElementById来取
	
   var d = new Date;
	
	for (var i = 0; i < 10000; i++){
		document.getElementById('PartA');
	}

	alert (new Date - d);


结果 :       百度      新浪
        IE6 : 很长      直接挂掉
        IE7 : 110       406
        FF2 : 18        19
        CHR : 15        17


从上面的结果可以得到结论:

1, 在循环10000次的情况下,2种方式的效率出现数量级的差距.而IE6完全没做优化.导致浏览器直接挂掉.

2, 第2段代码中在新浪的几百个节点里和在百度的十来个节点里document.getElementById的效率几乎是一样的,证明document.getElementById绝对没有做遍历节点的操作.getElementById里面最有可能执行的是一个类似这样的方法:
document.getElementById = function(id){
  //...doSomeThing
  return 节点集[id];
}



那么为什么会出现1的结论,我觉得不过是window.document.getElementId的scope chain比较长,以及方法调用的开销造成的.
为了证明这个,再做个测试.模拟document.getElementById的环境,然后按引用取.


    var c = new Array();
    document.getElementById = function(){
        return c[0];
    }
    var d = new Date;
    for (var i = 0; i < 10000; i++){
	document.getElementById('aa');
    }
    alert (new Date - d);



结果 :       百度      新浪
        IE6 : 未测      未测
        IE7 : 110       156
        FF2 : 16        16
        CHR : 15        9


跟上面第二段代码的结论比较可以看到, firefox和chrome下两者已经很接近了,IE7下还是有点点差距,IE6则完全没对这2个方法做优化.上次我说的大部分浏览器没有明确指出IE6,确实是我的疏忽.


结论: 很多浏览器确实对document.getElementById和document.getElementsByTagName做了优化,我们印象中document.getElementById会因为dom节点的操作而影响性能是不对的,那不过是普通查找scope chain和调用方法的开销.


今天试图看了下mozilla的js引擎源码,结果当然是完全看不懂,要是哪位看过的能指点一二,小弟十分感谢.





   发表时间:2009-08-19  
写道
ecma里无解.所以做了一些测试,分别在几百个节点的新浪首页和十多个节点的百度首页做了测试.等页面加载完之后分别执行下面这几段代码.测试5次取平均值.单位ms.测试document.getElementsByTagName的结果跟document.getElementById的差不多,所以这里只讨论后者.
 

getElementsByTagName测试了下在IE中好象比getElementById快一倍.

不知道楼主是怎么测试的.居然说是差不多.

 

纠正下022的这个错误.

0 请登录后投票
   发表时间:2009-08-19   最后修改:2009-08-19
猪也有理想 写道
写道
ecma里无解.所以做了一些测试,分别在几百个节点的新浪首页和十多个节点的百度首页做了测试.等页面加载完之后分别执行下面这几段代码.测试5次取平均值.单位ms.测试document.getElementsByTagName的结果跟document.getElementById的差不多,所以这里只讨论后者.
 

getElementsByTagName测试了下在IE中好象比getElementById快一倍.

不知道楼主是怎么测试的.居然说是差不多.

 

纠正下022的这个错误.


是的,IE下getElementsByTagName确实比getElementById快些,不过我这里不是在比较getElementsByTagName和getElementById他们2个的速度.而是比较它们2个和按引用来取的速度.

0 请登录后投票
   发表时间:2009-08-19  

深入讨论document.getElementById和document.getElementsByTagName

你的标题误导了我。不好意思。刚看完你的贴子。才知道你想说什么。

一开始看到你标题。我就屁颠屁颠的跑去测试了。没仔细看你的具体

抱歉

0 请登录后投票
   发表时间:2009-08-19  
嘿嘿,是我标题起的不好,已经改了.
0 请登录后投票
   发表时间:2009-08-19   最后修改:2009-08-19
var doc=document;
var d = new Date;  
 
for (var i = 0; i < 10000; i++){  
    doc.getElementById('PartA');  
}  
 
alert (new Date - d); 

这样快一点

另外我觉得你的结论可以这样说:直接应用dom节点变量确实比每次调用document.getElementById要快,不过document.getElementById没你们想的那么慢
0 请登录后投票
   发表时间:2009-08-19   最后修改:2009-08-19
edokeh 写道
var doc=document;
var d = new Date;  
 
for (var i = 0; i < 10000; i++){  
    doc.getElementById('PartA');  
}  
 
alert (new Date - d); 

这样快一点

另外我觉得你的结论可以这样说:直接应用dom节点变量确实比每次调用document.getElementById要快,不过document.getElementById没你们想的那么慢



其实没什么可比性,如果你的引用要路过较长的作用域链,或者它还是某个复杂函数的返回值,那比较结果还不一定呢.也许是我的例子举的不好,我的表达和你的理解还是有点偏差,我这里并没有想如何去优化document.getElementById从而让它更快一些.
0 请登录后投票
   发表时间:2009-08-19   最后修改:2009-08-19
从编程者出发,即便浏览器对getElementById有优化,但无论怎么优化,至少得多一层调用。直接保存引用,效率依旧更好。

更多的是一种编程习惯:用空间换取时间。

另:闭包的开销,Chrome和Safari等浏览器也有优化,深层闭包,也无多大影响。但作为一个良好的编码习惯,在保证可维护性的前提下,尽量减少闭包依旧是值得推崇的。

一切都是权衡。
0 请登录后投票
   发表时间:2009-08-19  
你怎么不用剑圣的头像了。桑原好挫啊
0 请登录后投票
   发表时间:2009-08-19   最后修改:2009-08-19
所以 方法调用返回值 vs 变量调用,它们的用时对比无法在同一个量级上。
——即便是优化了的js引擎内置对象的方法也是如此。

引用

……证明document.getElementById绝对没有做遍历节点的操作.getElementById里面最有可能执行的是一个类似这样的方法:
document.getElementById = function(id){
  //...doSomeThing
  return 节点集[id];
}

对于一部分浏览器这个结论我还是比较赞同的,引擎基于底层语言和内置hash有条件做各种内置方法的优化,
但是各个浏览器对js引擎内置对象的方法优化程度也良莠不齐,
像IE6/7那样未优化或优化远远不到位就更是要注意了。
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics