精华帖 (1) :: 良好帖 (7) :: 新手帖 (7) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2009-08-19
最后修改:2009-08-19
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引擎源码,结果当然是完全看不懂,要是哪位看过的能指点一二,小弟十分感谢. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-08-19
写道
ecma里无解.所以做了一些测试,分别在几百个节点的新浪首页和十多个节点的百度首页做了测试.等页面加载完之后分别执行下面这几段代码.测试5次取平均值.单位ms.测试document.getElementsByTagName的结果跟document.getElementById的差不多,所以这里只讨论后者.
getElementsByTagName测试了下在IE中好象比getElementById快一倍. 不知道楼主是怎么测试的.居然说是差不多.
纠正下022的这个错误. |
|
返回顶楼 | |
发表时间:2009-08-19
最后修改:2009-08-19
猪也有理想 写道
写道
ecma里无解.所以做了一些测试,分别在几百个节点的新浪首页和十多个节点的百度首页做了测试.等页面加载完之后分别执行下面这几段代码.测试5次取平均值.单位ms.测试document.getElementsByTagName的结果跟document.getElementById的差不多,所以这里只讨论后者.
getElementsByTagName测试了下在IE中好象比getElementById快一倍. 不知道楼主是怎么测试的.居然说是差不多.
纠正下022的这个错误.
|
|
返回顶楼 | |
发表时间:2009-08-19
深入讨论document.getElementById和document.getElementsByTagName 你的标题误导了我。不好意思。刚看完你的贴子。才知道你想说什么。 一开始看到你标题。我就屁颠屁颠的跑去测试了。没仔细看你的具体 抱歉 |
|
返回顶楼 | |
发表时间:2009-08-19
嘿嘿,是我标题起的不好,已经改了.
|
|
返回顶楼 | |
发表时间: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没你们想的那么慢 |
|
返回顶楼 | |
发表时间: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从而让它更快一些. |
|
返回顶楼 | |
发表时间:2009-08-19
最后修改:2009-08-19
从编程者出发,即便浏览器对getElementById有优化,但无论怎么优化,至少得多一层调用。直接保存引用,效率依旧更好。
更多的是一种编程习惯:用空间换取时间。 另:闭包的开销,Chrome和Safari等浏览器也有优化,深层闭包,也无多大影响。但作为一个良好的编码习惯,在保证可维护性的前提下,尽量减少闭包依旧是值得推崇的。 一切都是权衡。 |
|
返回顶楼 | |
发表时间:2009-08-19
你怎么不用剑圣的头像了。桑原好挫啊
|
|
返回顶楼 | |
发表时间:2009-08-19
最后修改:2009-08-19
所以 方法调用返回值 vs 变量调用,它们的用时对比无法在同一个量级上。
——即便是优化了的js引擎内置对象的方法也是如此。 引用 ……证明document.getElementById绝对没有做遍历节点的操作.getElementById里面最有可能执行的是一个类似这样的方法: document.getElementById = function(id){ //...doSomeThing return 节点集[id]; } 对于一部分浏览器这个结论我还是比较赞同的,引擎基于底层语言和内置hash有条件做各种内置方法的优化, 但是各个浏览器对js引擎内置对象的方法优化程度也良莠不齐, 像IE6/7那样未优化或优化远远不到位就更是要注意了。 |
|
返回顶楼 | |