<!--your preparation HTML code goes here-->
function createTestElement(threshold = 0.5) {
const element = document.createElement('div');
if (Math.random() > 0.8) {
element.setAttribute('data-test', 'foo');
}
while (Math.random() > threshold) {
element.append(createTestElement(threshold + 0.1));
}
return element;
}
const testElements = Array.from({
length: 100
}, () => createTestElement());
testElements.forEach((el) => {
const matches = el.querySelectorAll('[data-test]');
matches.forEach(() => {});
});
testElements.forEach((el) => {
if (el.querySelector('[data-test]')) {
const matches = el.querySelectorAll('[data-test]');
matches.forEach(() => {});
}
});
testElements.forEach((el) => {
const matches = el.querySelectorAll('[data-test]');
matches.forEach(() => {});
});
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
querySelectorAll | |
querySelector + querySelectorAll | |
querySelectorAll again (in case of caching) |
Test name | Executions per second |
---|---|
querySelectorAll | 18178.4 Ops/sec |
querySelector + querySelectorAll | 38450.6 Ops/sec |
querySelectorAll again (in case of caching) | 17060.7 Ops/sec |
The benchmark focuses on comparing the performance of DOM query operations using two different approaches in JavaScript: querySelectorAll
used alone versus a combination of querySelector
followed by querySelectorAll
. The specific operations being tested are as follows:
querySelectorAll
:
querySelectorAll
by itself, which retrieves all elements matching a given CSS selector.querySelectorAll('[data-test]')
, which returns all descendants with the attribute data-test
.querySelector + querySelectorAll
:
querySelector
and querySelectorAll
. Here, it first checks if an element has at least one matching element with querySelector('[data-test]')
before calling querySelectorAll
on it.data-test
attribute by skipping the querySelectorAll
call for those non-matching elements.querySelectorAll again (in case of caching)
:
querySelectorAll
:
querySelector + querySelectorAll
:
querySelectorAll
calls by first checking for the presence of matching elements, leading to better performance if many elements do not match.querySelector
introduces some overhead, which may not be beneficial if many elements do contain the matching attribute.The benchmark results indicate the number of executions per second for each method:
querySelector + querySelectorAll
: 54,223.91 executions/sec, performing notably well.querySelectorAll again (in case of caching)
: 34,062.99 executions/sec, demonstrating that reusing cached results may provide better performance under specific conditions.querySelectorAll
(first test): 32,685.01 executions/sec, which is the least efficient of the three as expected.In this benchmark, no specific JavaScript library is used, but the features employed are native to the JavaScript and DOM APIs. The capabilities of querySelector
and querySelectorAll
are built-in methods of the DOM API, allowing for efficient manipulation and querying of HTML elements.
getElementsByClassName
or getElementsByTagName
may be alternatives for scenarios where specific selectors aren't necessary, although they do not support complex CSS selectors like querySelectorAll
.This benchmark highlights the importance of understanding the context in which these querying methods are used, as performance can vary significantly based on the overall structure of the DOM and the presence of matching elements.