𝗣𝗿𝗼𝗼𝗳 𝗢𝗳 𝗔 𝗟𝗲𝘀𝘀 𝗘𝗳𝗳𝗶𝗰𝗶𝗲𝗻𝘁 𝗕𝗶𝗻𝗮𝗿𝘆 𝗦𝗲𝗮𝗿𝗰𝗵
我假设给定一个元素,它的所有子元素都是按顺序排列在文档中的,最快的方法应该是进行二进制搜索,比较元素的文档位置。然而,正如结论中所介绍的那样,该假设被拒绝。元素越多,性能潜力就越大。例如,如果你有256个元素,那么(最好)你只需要检查其中的16个!对于65536,只有256!性能增长到2倍!查看更多数字/统计数据。访问维基百科
(函数(构造函数){'使用严格';Object.defineProperty(constructor.protype,'parentIndex'{获取:函数(){var searchParent=this.parentElement;if(!searchParent)返回-1;var searchArray=searchParent.children,thisOffset=this.offset顶部,stop=搜索数组长度,p=0,增量=0;while(searchArray[p]!==此){if(searchArray[p]>this)停止=p+1,p-=增量;δ=(停止-p)>>>1;p+=增量;}返回p;}});})(window.Element||节点);
然后,使用它的方法是获取任何元素的“parentIndex”属性。例如,查看以下演示。
(函数(构造函数){'使用严格';Object.defineProperty(constructor.protype,'parentIndex'{获取:函数(){var searchParent=this.parentNode;如果(searchParent===null)返回-1;var childElements=搜索Parent.children,lo=-1,mi,hi=childElements.length;while(1+lo!==hi){mi=(hi+lo)>>1;if(!(this.compareDocumentPosition(childElements[mi])&0x2){hi=英里;继续;}lo=mi;}return childElements[hi]===这个?hi:-1;}});})(window.Element||节点);output.textContent=document.body.parentIndex;output2.textContent=文档.documentElement.parentIndex;
Body parentIndex是<b id=“output”></b><br/>documentElements parentIndex是<b id=“output2”></b>
限制
200000个元素上的二进制与线性搜索(可能会导致某些移动浏览器崩溃,小心!):
- 在这个测试中,我们将看到线性搜索与二进制搜索相比需要多长时间才能找到中间元素。为什么是中间元素?因为它位于所有其他位置的平均位置,所以它最能代表所有可能的位置。
二进制搜索
(函数(构造函数){'使用严格';Object.defineProperty(constructor.prototype,'parentIndexBinarySearch'{获取:函数(){var searchParent=this.parentNode;如果(searchParent===null)返回-1;var childElements=搜索Parent.children,lo=-1,mi,hi=childElements.length;while(1+lo!==hi){mi=(hi+lo)>>1;if(!(this.compareDocumentPosition(childElements[mi])&0x2){hi=英里;继续;}lo=mi;}return childElements[hi]===这个?hi:-1;}});})(window.Element||节点);test.inerHTML=“<div></div>”.重复(200e+3);//给它一些时间思考:requestAnimationFrame(函数(){var-child=test.childrens.item(99.9e+3);var start=performance.now(),end=Math.round(Math.random());for(var i=200+end;i--!==end;)控制台.assert(test.children.item(数学循环(99.9e+3+i+Math.random()).parentIndexBinarySearch);var end=性能.now();setTimeout(函数(){output.textContent='用二进制搜索'+((end-start)*10).toFixed(2)+'毫秒在一个包含20万个子元素的元素中找到第999千到101千个子元素。';test.remove();测试=空;//释放引用}, 125);}, 125);
<output id=output></output><div id=test style=可见性:隐藏;空白:预></div>
向后(`lastIndexOf`)线性搜索
(函数(t){“use strict”;vare=Array.prototype.lastIndexOf;Object.defineProperty(t.prototype,“parentIndexLinearSearch”,{get:function(){return e.call(t,this)}})})(window.Element | | Node);test.inerHTML=“<div></div>”.重复(200e+3);//给它一些时间思考:requestAnimationFrame(函数(){var-child=test.childrens.item(99e+3);var start=performance.now(),end=Math.round(Math.random());for(var i=2000+结束;i-!==结束;)控制台.assert(test.children.item(数学循环(99e+3+i+Math.random()).parentIndexLinearSearch);var end=性能.now();setTimeout(函数(){output.textContent='在一个包含20万个子元素的元素中,查找第999000到101000个子元素需要花费反向线性搜索'+(end-start).toFixed(2)+'毫秒。';test.remove();test=null;//释放引用}, 125);});
<output id=output></output><div id=test style=可见性:隐藏;空白:预></div>
转发(`indexOf`)线性搜索
(函数(t){“use strict”;var e=Array.prototype.indexOf;Object.defineProperty(t.prototype,“parentIndexLinearSearch”,{get:function(){return e.call(t,this)}})})(window.Element||Node);test.inerHTML=“<div></div>”.重复(200e+3);//给它一些时间思考:requestAnimationFrame(函数(){var-child=test.childrens.item(99e+3);var start=performance.now(),end=Math.round(Math.random());for(var i=2000+end;i--!==end;)控制台.assert(test.children.item(数学循环(99e+3+i+Math.random()).parentIndexLinearSearch);var end=性能.now();setTimeout(函数){output.textContent='向前线性搜索'+(end-start).toFixed(2)+'毫秒后,在一个包含20万个子元素的元素中找到了999000到101000个子元素。';test.remove();test=null;//释放引用}, 125);});
<output id=output></output><div id=test style=可见性:隐藏;空白:预></div>
上一个ElementSibling计数器搜索
统计PreviousElementSibling的数量以获取parentIndex。
(函数(构造函数){'使用严格';Object.defineProperty(constructor.prototype,'parentIndexSiblingSearch'{获取:函数(){var i=0,cur=this;做{cur=cur.previousElementSibling;++i;}while(cur!==空)返回i//返回3}});})(window.Element||节点);test.inerHTML=“<div></div>”.重复(200e+3);//给它一些时间思考:requestAnimationFrame(函数(){var-child=test.childrens.item(99.95e+3);var start=performance.now(),end=Math.round(Math.random());for(var i=100+end;i--!==end;)控制台.assert(test.children.item(数学循环(99.95e+3+i+Math.random()).parentIndexSiblingSearch);var end=性能.now();setTimeout(函数(){output.textContent='在一个包含20万个子元素的元素中,需要使用PreviousElementSibling搜索'+((end-start)*20).toFixed(2)+'毫秒才能找到999000到101000个子元素。';test.remove();test=null;//释放引用}, 125);});
<output id=output></output><div id=test style=可见性:隐藏;空白:预></div>
无搜索
对于基准测试,如果浏览器优化了搜索,测试结果会是什么。
test.inerHTML=“<div></div>”.重复(200e+3);//给它一些时间思考:requestAnimationFrame(函数(){var start=performance.now(),end=Math.round(Math.random());for(var i=2000+end;i--!==end;)console.assert(true);var end=性能.now();setTimeout(函数(){output.textContent='在一个包含20万个子元素的元素中,要找到第999千到101千个子元素,需要进行no搜索'+(end-start).toFixed(2)+'毫秒。';test.remove();test=null;//释放引用}, 125);});
<output id=output></output><br/><div id=test style=可见性:隐藏>
冲撞
然而,在Chrome中查看结果后,结果与预期相反。愚蠢的向前线性搜索令人惊讶地达到187毫秒,比二进制搜索快3850%。显然,Chrome以某种方式神奇地超过了控制台资产
并对其进行了优化,或者(更乐观地说)Chrome内部对DOM使用了数字索引系统,该内部索引系统通过应用于数组原型索引
在上使用时HTML集合
对象。