Skip to content

Instantly share code, notes, and snippets.

@prettydiff
Last active September 18, 2021 03:19
Show Gist options
  • Save prettydiff/b39045cacae8d8c4a3ec044e538533dc to your computer and use it in GitHub Desktop.
Save prettydiff/b39045cacae8d8c4a3ec044e538533dc to your computer and use it in GitHub Desktop.
dom vs queryselector #jsbench #jsperf (https://jsbench.github.io/#b39045cacae8d8c4a3ec044e538533dc) #jsbench #jsperf
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>dom vs queryselector #jsbench #jsperf</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<script src="./suite.js"></script>
</head>
<body>
<h1>Open the console to view the results</h1>
<h2><code>cmd + alt + j</code> or <code>ctrl + alt + j</code></h2>
</body>
</html>
"use strict";
(function (factory) {
if (typeof Benchmark !== "undefined") {
factory(Benchmark);
} else {
factory(require("benchmark"));
}
})(function (Benchmark) {
var suite = new Benchmark.Suite;
Benchmark.prototype.setup = function () {
const dom = function browser_dom() {
// getAncestor - A method to walk up the DOM towards the documentElement.
// * identifier: string - The string value to search for.
// * selector: "class", "id", "name" - The part of the element to compare the identifier against.
const getAncestor = function browser_dom_getAncestor(identifier, selector) {
// eslint-disable-next-line
let start = (this === document) ? document.documentElement : this;
const test = function browser_dom_getAncestor_test() {
if (selector === "class") {
if (start.getAttribute("class") === identifier) {
return true;
}
return false;
}
if (selector === "id") {
if (start.getAttribute("id") === identifier) {
return true;
}
return false;
}
if (start.nodeName.toLowerCase() === identifier) {
return true;
}
return false;
};
if (start === null || start === undefined) {
return null;
}
if (start === document.documentElement || test() === true) {
return start;
}
do {
start = start.parentNode;
if (start === null) {
return null;
}
} while (start !== document.documentElement && test() === false);
return start;
},
// getElementByAttribute - Search all descendant elements containing a matching attribute with matching value and returns an array of corresponding elements.
// * name: string - The name of the attribute to search for. An empty string means accept every attribute name.
// * value: string - The attribute value to search for. An empty string means accept any attribute value.
getElementsByAttribute = function browser_dom_getElementsByAttribute(name, value) {
// eslint-disable-next-line
const start = (this === document) ? document.documentElement : this, attrs = start.getNodesByType(2), out = [];
if (typeof name !== "string") {
name = "";
}
if (typeof value !== "string") {
value = "";
}
attrs.forEach(function browser_dom_getElementsByAttribute_each(item) {
if (item.name === name || name === "") {
if (item.value === value || value === "") {
out.push(item.ownerElement);
}
}
});
return out;
},
// getElementsByText - Returns an array of descendant elements containing the white space trimmed text.
// * textValue: string - The text to match. The value must exactly match the complete text node value after trimming white space.
// * castSensitive: boolean - Whether case sensitivity should apply.
getElementsByText = function browser_dom_getElementsByText(textValue, caseSensitive) {
// eslint-disable-next-line
const start = (this === document) ? document.documentElement : this, texts = start.getNodesByType(3), out = [];
if (typeof textValue !== "string") {
textValue = "";
}
else {
textValue = textValue.replace(/^\s+/, "").replace(/\s+$/, "");
}
if (typeof caseSensitive !== "boolean") {
caseSensitive = false;
}
texts.forEach(function browser_dom_getElementsByText_each(item) {
const text = (caseSensitive === true)
? item.textContent.toLowerCase()
: item.textContent;
if (textValue === "" && text.replace(/\s+/, "") !== "") {
out.push(item.parentElement);
}
else if (textValue !== "" && text.replace(/^\s+/, "").replace(/\s+$/, "") === textValue) {
out.push(item.parentElement);
}
});
return out;
},
// getNodesByType - Returns an array of DOM nodes matching the provided node type.
// * typeValue: string|number = The value must be a node type name or a node type number (0-12)
// - An empty string, "all", or 0 means gather all descendant nodes regardless of type.
// - For standard values see: https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
getNodesByType = function browser_dom_getNodesByType(typeValue) {
const valueString = (typeof typeValue === "string") ? `${typeValue.toLowerCase().replace("_node", "")}_node` : "", numb = (isNaN(Number(typeValue)) === false)
? Math.round(Number(typeValue))
: null, output = [], child = function browser_dom_getNodesByType_child(recurse) {
const children = recurse.childNodes, len = children.length, attributes = recurse.attributes, atLen = attributes.length;
let a = 0;
// Special functionality for attribute types.
if (atLen > 0 && (types === 2 || types === 0)) {
do {
output.push(attributes[a]);
a = a + 1;
} while (a < atLen);
}
a = 0;
if (len > 0) {
do {
if (children[a].nodeType === types || types === 0) {
output.push(children[a]);
}
if (children[a].nodeType === 1) {
//recursion magic
browser_dom_getNodesByType_child(children[a]);
}
a = a + 1;
} while (a < len);
}
}, types = (function browser_dom_getNodesByType_types() {
if (valueString === "element_node") {
return 1;
}
if (valueString === "attribute_node") {
return 2;
}
if (valueString === "text_node") {
return 3;
}
if (valueString === "cdata_section_node") {
return 4;
}
if (valueString === "entity_reference_node") {
return 5;
}
if (valueString === "entity_node") {
return 6;
}
if (valueString === "processing_instruction_node") {
return 7;
}
if (valueString === "comment_node") {
return 8;
}
if (valueString === "document_node") {
return 9;
}
if (valueString === "document_type_node") {
return 10;
}
if (valueString === "document_fragment_node") {
return 11;
}
if (valueString === "notation_node") {
return 12;
}
if (numb !== null && numb < 13 && numb > -1) {
return numb;
}
return 0;
}());
// eslint-disable-next-line
child((this === document) ? document.documentElement : this);
return output;
};
// Create a document method
document.getElementsByAttribute = getElementsByAttribute;
document.getNodesByType = getNodesByType;
document.getElementsByText = getElementsByText;
// Ensure dynamically created elements get these methods too
Element.prototype.getAncestor = getAncestor;
Element.prototype.getElementsByAttribute = getElementsByAttribute;
Element.prototype.getNodesByType = getNodesByType;
Element.prototype.getElementsByText = getElementsByText;
};dom();
};
suite.add("dom method - id", function () {
// dom method - id
document.getElementById("canvas");
});
suite.add("dom method - class", function () {
// dom method - class
document.getElementsByClassName("sa-success");
});
suite.add("dom method - chain by id", function () {
// dom method - chain by id
document.getElementById("canvas").getElementsByTagName("div");
});
suite.add("dom method - chain by class", function () {
// dom method - chain by class
document.getElementsByClassName("app")[0].getElementsByClassName("app__foot")[0].getElementsByTagName("table");
});
suite.add("query selector - id", function () {
// query selector - id
document.querySelector("#canvas");
});
suite.add("query selector - class", function () {
// query selector - class
document.querySelector(".sa-success");
});
suite.add("query selector - chain by id", function () {
// query selector - chain by id
document.querySelector("#canvas div");
});
suite.add("query selector - chain by class", function () {
// query selector - chain by class
document.querySelector(".app .app_foot table");
});
suite.add("query selector all - id", function () {
// query selector all - id
document.querySelectorAll("#canvas");
});
suite.add("query selector all - class", function () {
// query selector all - class
document.querySelectorAll(".sa-success");
});
suite.add("query selector all - chain by id", function () {
// query selector all - chain by id
document.querySelectorAll("#canvas div");
});
suite.add("query selector all - chain by class", function () {
// query selector all - chain by class
document.querySelectorAll(".app .app_foot table");
});
suite.add("custom dom method - getElementsByAttribute", function () {
// custom dom method - getElementsByAttribute
document.getElementsByAttribute("href");
});
suite.add("custom dom method - getAncestor", function () {
// custom dom method - getAncestor
document.getElementsByTagName("table")[0].getAncestor("body", "tag");
});
suite.add("custom dom method - getNodesByType", function () {
// custom dom method - getNodesByType
document.getNodesByType("comment");
});
suite.add("custom dom method - getElementsByText", function () {
// custom dom method - getElementsByText
document.getElementsByText("Run");
});
suite.on("cycle", function (evt) {
console.log(" - " + evt.target);
});
suite.on("complete", function (evt) {
console.log(new Array(30).join("-"));
var results = evt.currentTarget.sort(function (a, b) {
return b.hz - a.hz;
});
results.forEach(function (item) {
console.log((idx + 1) + ". " + item);
});
});
console.log("dom vs queryselector #jsbench #jsperf");
console.log(new Array(30).join("-"));
suite.run();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment