我问过this question,结果发现当从元素中删除属性时,首先使用elem.xxx!==undefined
检查元素是否存在会使运行时更快。 Proof
为什么会更快? {1}}方法无论你采用哪种方式。
答案 0 :(得分:5)
嗯,首先需要知道的是elem.xxx
与elem.getAttribute()
或与属性相关的任何其他方法都不相同。
elem.xxx
是DOM元素的属性,而DOM内部的HTML上的属性和元素都相似但不同。例如,请使用以下DOM元素:<a href="#">
和此代码:
//Let say var a is the <a> tag
a.getAttribute('href');// == #
a.href;// == http://www.something.com/# (i.e the complet URL)
但是,请使用自定义属性:<a custom="test">
//Let say var a is the <a> tag
a.getAttribute('custom');// == test
a.custom;// == undefined
因此,您无法真正比较两者的速度,因为它们无法达到相同的效果。但是一个显然更快,因为属性是快速访问数据,而属性使用get / hasAttribute DOM函数。
现在,为什么没有条件更快?仅仅因为removeAttribute
并不关心属性是否缺失,它会检查它是否属于。
因此在hasAttribute
之前使用removeAttribute
就像执行两次检查一样,但条件有点慢,因为它需要检查运行代码是否满足条件。
答案 1 :(得分:2)
我怀疑速度提升的原因是追踪树。
加州大学欧文分校的Andreas Gal和Michael Franz在他们的论文Incremental Dynamic Code Generation with Trace Trees中首次提出了追踪树。
在他的博客文章Tracing the Web中,Andreas Gal(该论文的合着者)解释了跟踪即时编译器的工作原理。
为了解释跟踪JIT编译器的可能性(因为我对该主题的了解并不深刻),跟踪JIT编译器会执行以下操作:
true
语句的if
分支的次数)。现在让我们来看看您的代码并了解导致速度提升的原因:
if (elem.hasAttribute("xxx")) {
elem.removeAttribute("xxx");
}
此代码具有代码路径(即if
语句)。请记住,跟踪JIT只会优化代码路径而不是整个函数。这就是我认为正在发生的事情:
hasAttribute
的额外函数调用的开销,这不是JIT编译的,因为它不是条件代码路径的一部分(花括号之间的代码)。elem.removeAttribute("xxx");
在此测试用例中,我们没有任何条件代码路径。因此,JIT编译器永远不会启动。因此代码很慢。
if (elem.xxx !== undefined) {
elem.removeAttribute("xxx");
}
这与第一个具有一个显着差异的测试用例相同:
elem.xxx
或undefined
的数据类型每次迭代都不会更改,因此优化会使条件检查更快。当然这只是我的猜测。我不知道JavaScript引擎的内部结构,因此我的答案不是规范的。但是我认为这是一个很好的教育猜测。
答案 2 :(得分:0)
您的证明不正确......
elem.class !== undefined
始终评估为false
,因此永远不会调用elem.removeAttribute("class")
,因此,此测试将始终更快。
elem
使用的正确属性为className
,例如:
typeof elem.className !== "undefined"
答案 3 :(得分:0)
正如Karl-AndréGagnon指出的那样,访问 [native] JavaScript属性并调用 DOM函数/属性是两个不同的操作
某些 DOM属性通过DOM IDL公开为 JavaScript属性;这些不与 adhoc JS属性相同,并且需要DOM访问权限。此外,即使公开了 DOM属性,也与 DOM属性没有严格的关系!
例如,inputElm.value = "x"
将不更新 DOM属性,即使该元素将显示并报告更新的值。如果目标要处理 DOM属性,唯一正确的方法是使用hasAttribute/setAttribute
等。
我一直致力于为不同的函数调用推导出一个“公平”的微基准测试,但它相当困难,并且发生了不同优化的很多。这里my best result,我将用它来论证我的情况。
请注意,没有 if
或removeAttribute
混淆了结果,我只关注 来访问DOM / JS属性。此外,我试图排除速度差异仅仅是由函数调用引起的声明,并且我分配结果以避免公然的浏览器优化。 YMMV。
观察:
JS属性的访问是快速。这是预期的 1,2
调用函数可能会比直接属性访问 1 带来更高的成本,但不会像 DOM属性或 DOM函数<一样慢/ em>的。也就是说,它不仅仅是一个“函数调用”,它使hasAttribute
变得如此慢。
DOM属性访问较慢比原生 JS属性访问;但是,DOM属性和浏览器之间的性能差别很大。我更新的微基准测试显示了DOM访问的趋势 - 无论是通过DOM属性还是DOM功能 - 可能比本机JS属性访问 2 慢。
< / LI> 醇>回到顶端:在元素上访问非DOM [JS]属性与访问 DOM属性完全不同较少的 DOM属性,在同一元素上。正是这种根本区别,以及跨浏览器的方法之间的优化(或缺乏),这些都是观察到的性能差异的原因。
1 IE 10做了一些聪明的技巧,其中假函数调用非常快(我怀疑调用已被删除),即使它具有糟糕的JS属性访问。但是,考虑到IE是一个异常值或仅仅强化了函数调用而不是引入了本质上较慢的行为,这并没有减损我的主要论点:它是 DOM 访问这基本上是慢的。
2 我想说DOM属性访问 更慢,但FireFox对input.value
做了一些惊人的优化(但不是img.src
) 。这里发生了一些特殊的魔法。 Firefox不会优化 DOM属性访问。
并且,不同的浏览器可能会显示完全不同的结果..但是,我不认为必须考虑使用if
或removeAttribute
的任何“魔法”来至少隔离我相信的内容成为“性能问题”:实际使用DOM 。