Javascript 有没有办法重构此代码以提高性能?
所以我有这个问题要做练习。代码可以工作,但我希望提高代码的性能,这样就不会出现时间复杂度问题(例如,没有嵌套for循环)。但我似乎找不到办法 任务是创建一个JavaScript选择引擎,该引擎将返回给定CSS选择器的DOM元素。我无法使用任何外部库或文档。querySelector/queryselectorAll HTML正文如下所示Javascript 有没有办法重构此代码以提高性能?,javascript,html,node.js,Javascript,Html,Node.js,所以我有这个问题要做练习。代码可以工作,但我希望提高代码的性能,这样就不会出现时间复杂度问题(例如,没有嵌套for循环)。但我似乎找不到办法 任务是创建一个JavaScript选择引擎,该引擎将返回给定CSS选择器的DOM元素。我无法使用任何外部库或文档。querySelector/queryselectorAll HTML正文如下所示 <body> <div></div> <div id="some_id" class="some_c
<body>
<div></div>
<div id="some_id" class="some_class some_other_class"></div>
<img id="some_other_id" class="some_class some_other_class"></img>
<input type="text">
</body>
元素具有内置的方法,允许您检查它们是否与特定选择器匹配:。对于一个已经解决的问题,不必重新发明轮子就容易多了。获取文档中的所有元素,然后在每次调用
$
时,返回这些元素的数组,并根据它们是否匹配选择器进行筛选:
const getAllChildren=(父级,结果=[])=>{
Array.prototype.forEach.call(
父母,孩子,
(儿童)=>{
结果:推(儿童);
getAllChildren(child,results);
}
);
返回结果;
};
var$=函数(选择器){
返回getAllChildren(document.body)
.filter(elm=>elm.matches(选择器));
}
console.log($(“div”)//应返回2个div
console.log($(“img.some_class”)//应返回1个img
log($(“#some_id”)//应返回1个DIV
console.log($(“.some_class”)//应该返回1个DIV和1个IMG
log($(“input#some_id”)//应该返回一个空数组
console.log($($div#some_id.some_class))//应该返回1个div
log($($div.some_class#some_id))//应返回1个div
因为他们询问了性能,所以您可能希望改用a,这仍然是遍历DOMTree(无递归)的最快方法<代码>$=(选择器)=>{const walker=document.createTreeWalker(document.body,NodeFilter.SHOW_元素,null);const nodes=[];while(walker.nextNode()){if(walker.currentNode.matches(选择器)){nodes.push(walker.currentNode)}返回节点};始终返回NodeFilter枚举(FILTER\u ACCEPT),返回布尔值将导致某些DOM结构出现问题(例如,搜索“#引用窗格表”
将在Chrome上失败,原因我不确定……)。但是无论如何,在while循环中进行过滤,就像我在第一条注释中所做的那样,实际上(令人惊讶地)比在NodeFilter函数中进行过滤快两倍。谢谢,我看到您使用的是passingnull
,而不是完全忽略参数。它看起来像是说只有null
的值默认为FILTER\u ACCEPT
,但MDN说该参数是完全可选的(并且默认接受)null
可能是安全的,我想我对旧IE有问题,并且养成了总是传递null
的习惯。
var $ = function (selector) {
if (typeof selector !== "string"){
throw TypeError("Please enter a selector in a string format")
}
let results = [];
let classes = getClasses();
let hasClass, hasID, str, a
if (document.getElementsByTagName(selector)){
hasClass = selector.includes(".") ? true : false
hadID = selector.includes("#") ? true : false
}
if (hasClass && hasID) {
let i = 0;
while (i < classes.length){
if (selector.includes(classes[i])) {
str = classes[i];
a = document.getElementsByClassName(str);
if (selector.includes(a[i].id)) results.push(a[i]);
}
i++
}
} else if (hasClass) {
let list1, list2;
for (i = 0; i < classes.length; i++) {
if (selector.includes(classes[i])) {
str = classes[i];
a = document.getElementsByClassName(str);
for (j = 0; j < a.length; j++) {
if (selector.charAt(0) === ".") {
results.push(a[j]);
} else if (selector.includes(a[j].tagName.toLowerCase())) {
results.push(a[j]);
}
}
}
}
} else if (hasID) {
if (selector.charAt(0) === "#") results.push(window[selector.substring(selector.indexOf("#") + 1, selector.length)]);
} else {
for (var i = 0; i < t.length; i++) results.push(t[i]);
}
return results;
}
function getClasses(){
let nodesArray = document.body.childNodes
let results = [];
i = 0;
while (i < nodesArray.length){
let element = nodesArray[i].nodeName;
if (!element.includes("#")){
for (j = 0; j < nodesArray[i].classList.length; j++) results.push(nodesArray[i].classList[j]);
}
i++
}
let x = Array.from(new Set(results))
console.log(x)
return x
}
$("div") - Should return 2 DIVs
$("img.some_class") - Should return 1 IMG
$("#some_id") - Should return 1 DIV
$(".some_class") - Should return 1 DIV and 1 IMG
$("input#some_id") - Should return an empty array
$("div#some_id.some_class") - Should return 1 DIV
$("div.some_class#some_id") - Should return 1 DIV