elem.xxx
并不等同于elem.getAttribute()
或者其他与属性相关的方法。elem.xxx
是一个属性,而HTML中的属性和元素在DOM内部也是相似但有所不同。举个例子,看下面这个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
现在,为什么没有条件会更快呢?简单地说,removeAttribute
不关心属性是否缺失,它只检查是否存在。
因此,在removeAttribute
之前使用hasAttribute
就像做两次检查,但条件会稍微慢一些,因为它需要检查条件是否满足才能运行代码。
if
需要被处理,这就是为什么它稍微慢一点的原因。 - Karl-André Gagnonif()
需要更多的计算资源。 - Karl-André Gagnonel.xxx
和 getAttribute
不是同一个东西。el.class
会始终等于 undefined,因为 class
属性应该是 el.className
。重要的是,属性和点表示法不是同一回事。 - Karl-André Gagnonif (elem.hasAttribute("xxx")) {
elem.removeAttribute("xxx");
}
if
语句)。请记住,跟踪JIT只会优化代码路径而不是整个函数。我认为正在发生以下情况:
hasAttribute
,因为它不是条件代码路径(花括号之间的代码)的一部分,所以没有被JIT编译。elem.removeAttribute("xxx");
if (elem.xxx !== undefined) {
elem.removeAttribute("xxx");
}
elem.xxx
或undefined
的数据类型在每次迭代中都没有改变,这种优化使得条件检查更快。正如Karl-André Gagnon所指出的那样,访问[本地] JavaScript属性和调用DOM函数/属性是两个不同的操作。
一些DOM属性通过DOM IDL作为JavaScript属性公开;这些与adhoc JS属性不同,并需要DOM访问。此外,即使DOM属性被公开,也没有与DOM属性的严格关系!
例如,inputElm.value = "x"
将不会更新DOM属性,即使元素将显示并报告更新后的值。如果目标是处理DOM属性,唯一正确的方法是使用hasAttribute/setAttribute
等。
我一直在努力推导出一个“公平”的微基准测试来测试不同的函数调用,但这相当困难,因为有很多不同的优化发生。这里是我的最佳结果,我将用它来支持我的观点。
请注意,没有if
或removeAttribute
来混淆结果,我只关注DOM/JS属性访问。此外,我试图排除速度差异仅仅是由于函数调用引起的,并且我分配结果以避免明显的浏览器优化。你的结果可能会有所不同。
观察结果:
访问 JS 属性 是很 快速 的。这是可以预期的1,2
调用函数可能比直接属性访问成本更高1,但并不像 DOM 属性 或 DOM 函数 那么慢。也就是说,hasAttribute
并不仅仅是一个 "函数调用" 使它变得如此缓慢。
DOM 属性 访问比本地 JS 属性 访问要慢;然而,性能在 DOM 属性和浏览器之间有很大差异。我的更新的微基准测试显示了一个趋势,即 DOM 访问 - 无论是通过 DOM 属性还是 DOM 函数 - 可能 比本机 JS 属性访问更慢2。
1 IE 10做了一些聪明的技巧,其中虚假函数调用非常快(我怀疑调用已被省略),即使它具有可怕的JS属性访问。然而,考虑到IE是一个异常值或仅仅是加强函数调用不是引入固有较慢行为的论点,并没有削弱我的主要论点:基本上是DOM访问更慢。
2 我很想说DOM属性访问更慢,但FireFox对input.value
进行了一些惊人的优化(但不包括img.src
)。这里发生了一些特殊的魔法。Firefox不会优化DOM属性访问。
而且,不同的浏览器可能展示完全不同的结果...然而,我认为至少可以通过隔离我认为是“性能问题”的实际使用DOM来排除任何关于if
或removeAttribute
的“魔法”。
你的证明是错误的...
elem.class !== undefined
总是评估为 false
,所以 elem.removeAttribute("class")
从未被调用,因此,这个测试将始终更快。
在 elem
上正确使用的属性是 className
,例如:
typeof elem.className !== "undefined"
elem.xxx
的测试编辑也表明它更快。我现在会更新我的“证明”。 - dayuloli
.prop
的内容。但即使考虑到el.xxx
比hastAttribute
更快,为什么使用el.xxx
进行检查然后再删除属性仍然比不经检查直接删除属性更快呢? - dayuloli"class"
属性是通过elem.className
而不是elem.class
引用的,因为class
是Javascript中的保留字。在jsPerf中,你必须做的第一件事就是确保代码在测量性能之前实际上是可行的。 - jfriend00