getElementById 与 getElementsByClassName 与 querySelector 的性能

bra*_*w98 6 javascript benchmarking dom-manipulation

我正在dev.mozilla 中阅读有关 dom 操作的主题,我遇到了一条建议我们使用 querySelector 进行元素选择的声明:

请注意,与 JavaScript 中的许多内容一样,有多种方法可以选择元素并将对它的引用存储在变量中。Document.querySelector() 是推荐的现代方法...

但是,当我进行测试时,我意识到getElementsByClassName()是迄今为止最好的元素选择方法。为什么它比getElementById()更快?为什么 mozilla 开发指南仍然推荐使用querySelector()即使它是其中最慢的一个?

Use*_*ser 11

document.querySelector的主要优点是易于使用更复杂的 CSS 查询。

const loginFields = document.querySelector("form.login input");
if (loginFields.some((field) => field.value.trim() === "") {
    alert("Please fill in all fields");
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用document.getElementsByClassName和Element.getElementsByTagName。

const loginFields = document.getElementsByClassName(".login")[0]
    .getElementsByTagName("input");
if (loginFields.some((field) => field.value.trim() === "") {
    alert("Please fill in all fields");
}
Run Code Online (Sandbox Code Playgroud)

您可能已经注意到,您通常会将返回结果存储到常量/变量中。你(通常)不应该在 for/while 循环中调用它。


关于(存档的)性能测试,它看起来很不公平,因为除了类测试之外的所有测试都将运行两个查询。

JSPerf 测试


所以我决定做更多测试。在该页面的 HTML 中,我将 id“codeOne”添加到第一个具有“code”类的元素。

HTML代码

然后我进行了四次测试。

JavaScript 测试结果

根据这些测试结果,我可以得出结论,使用 id (691ms) 的 getElementById明显获胜,使用 id (749ms) 的 querySelector位居第二。这是因为id 很容易查找,因为浏览器从 Internet Explorer 复制了此功能,而 Internet Explorer 是过去最主要的浏览器。您甚至可以像使用变量一样使用 ids。

使用 id 变量进行 JavaScript 测试

请不要这样做,因为它的可读性较差。它也没有更快。

当我们查看使用 class 的测试时,我们可以看到getElementsByClassName (778ms)和querySelector (1460ms)之间存在巨大的性能差异。这是因为前者只会查找 classNames,而后者会做一些额外的检查,因为它可以使用像“#id.class[attr="value"]”或“form > input”这样的复杂查询。


最后的结论是,为了简单起见,您可以对一个元素使用 document.querySelector,对多个元素使用 document.querySelectorAll,因为任何 CSS 查询都可以工作。理论上,函数 getElementById 和 getElementsByClassName(以及 getElementsByTagName,不包括在内)应该始终更快,但实际上这不会影响网站的性能。您(可能)不会在循环中调用这些函数,因此您可以将结果存储在变量中。