मैं परिकल्पना करता हूं जिसने एक तत्व दिया है जहां उसके सभी बच्चों को क्रमिक रूप से दस्तावेज़ पर आदेश दिया गया है, सबसे तेज़ तरीका द्विआधारी खोज करना चाहिए, तत्वों के दस्तावेज़ पदों की तुलना करना। हालांकि, निष्कर्ष में पेश की गई परिकल्पना को खारिज कर दिया गया है। आपके पास जितने अधिक तत्व होंगे, प्रदर्शन की क्षमता उतनी ही अधिक होगी। उदाहरण के लिए, यदि आपके पास 256 तत्व थे, तो (आशावादी) आपको केवल उनमें से 16 की जांच करनी होगी! 65536 के लिए, केवल 256! प्रदर्शन 2 की शक्ति तक बढ़ता है! अधिक संख्या / आंकड़े देखें। विकिपीडिया पर जाएँ
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndex', {
get: function() {
var searchParent = this.parentElement;
if (!searchParent) return -1;
var searchArray = searchParent.children,
thisOffset = this.offsetTop,
stop = searchArray.length,
p = 0,
delta = 0;
while (searchArray[p] !== this) {
if (searchArray[p] > this)
stop = p + 1, p -= delta;
delta = (stop - p) >>> 1;
p += delta;
}
return p;
}
});
})(window.Element || Node);
फिर, जिस तरह से आप इसका उपयोग करते हैं, वह किसी भी तत्व की 'पैरेंटइन्डेक्स' संपत्ति प्राप्त करने से होता है। उदाहरण के लिए, निम्नलिखित डेमो देखें।
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndex', {
get: function() {
var searchParent = this.parentNode;
if (searchParent === null) return -1;
var childElements = searchParent.children,
lo = -1, mi, hi = childElements.length;
while (1 + lo !== hi) {
mi = (hi + lo) >> 1;
if (!(this.compareDocumentPosition(childElements[mi]) & 0x2)) {
hi = mi;
continue;
}
lo = mi;
}
return childElements[hi] === this ? hi : -1;
}
});
})(window.Element || Node);
output.textContent = document.body.parentIndex;
output2.textContent = document.documentElement.parentIndex;
Body parentIndex is <b id="output"></b><br />
documentElements parentIndex is <b id="output2"></b>
सीमाएं
- समाधान का यह कार्यान्वयन IE8 और उसके नीचे काम नहीं करेगा।
बाइनरी वीएस रैखिक खोज 200 हजार तत्वों पर (कुछ मोबाइल ब्राउज़रों को नष्ट कर सकता है, बीवेयर!):
- इस परीक्षण में, हम देखेंगे कि एक रैखिक खोज के लिए मध्य तत्व वी.एस. को एक द्विआधारी खोज खोजने में कितना समय लगता है। मध्य तत्व क्यों? क्योंकि यह अन्य सभी स्थानों के औसत स्थान पर है, इसलिए यह सभी संभावित स्थानों का सबसे अच्छा प्रतिनिधित्व करता है।
द्विआधारी खोज
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndexBinarySearch', {
get: function() {
var searchParent = this.parentNode;
if (searchParent === null) return -1;
var childElements = searchParent.children,
lo = -1, mi, hi = childElements.length;
while (1 + lo !== hi) {
mi = (hi + lo) >> 1;
if (!(this.compareDocumentPosition(childElements[mi]) & 0x2)) {
hi = mi;
continue;
}
lo = mi;
}
return childElements[hi] === this ? hi : -1;
}
});
})(window.Element || Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99.9e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=200 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99.9e+3+i+Math.random())).parentIndexBinarySearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the binary search ' + ((end-start)*10).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
}, 125);
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
पीछे की ओर (`lastIndexOf`) रैखिक खोज
(function(t){"use strict";var e=Array.prototype.lastIndexOf;Object.defineProperty(t.prototype,"parentIndexLinearSearch",{get:function(){return e.call(t,this)}})})(window.Element||Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=2000 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99e+3+i+Math.random())).parentIndexLinearSearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the backwards linear search ' + (end-start).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
आगे की ओर (`indexOf`) रैखिक खोज
(function(t){"use strict";var e=Array.prototype.indexOf;Object.defineProperty(t.prototype,"parentIndexLinearSearch",{get:function(){return e.call(t,this)}})})(window.Element||Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=2000 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99e+3+i+Math.random())).parentIndexLinearSearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the forwards linear search ' + (end-start).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
पिछला ई-आधार खोज काउंटर खोज
पेरेंटइंडेक्स प्राप्त करने के लिए पिछले ई-कॉमर्स की संख्या की गणना करता है।
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndexSiblingSearch', {
get: function() {
var i = 0, cur = this;
do {
cur = cur.previousElementSibling;
++i;
} while (cur !== null)
return i; //Returns 3
}
});
})(window.Element || Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99.95e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=100 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99.95e+3+i+Math.random())).parentIndexSiblingSearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the PreviousElementSibling search ' + ((end-start)*20).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
कोई खोज नहीं
बेंचमार्किंग के लिए यदि ब्राउज़र खोज को अनुकूलित करता है तो परीक्षण का परिणाम क्या होगा।
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var start=performance.now(), end=Math.round(Math.random());
for (var i=2000 + end; i-- !== end; )
console.assert( true );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the no search ' + (end-start).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden></div>
द कंक्लूज़न
हालाँकि, क्रोम में परिणाम देखने के बाद, परिणाम वही हैं जो अपेक्षित था। द्विआधारी खोज की तुलना में डम्बर फॉरवर्ड रैखिक खोज एक आश्चर्यजनक 187 एमएस, 3850% थी। जाहिर है, क्रोम ने किसी तरह जादुई रूप से console.assert
इसे आउटसोर्स किया और इसे दूर अनुकूलित किया, या (अधिक आशावादी रूप से) क्रोम आंतरिक रूप से डोम के लिए संख्यात्मक अनुक्रमण प्रणाली का उपयोग करता है, और यह आंतरिक अनुक्रमण प्रणाली Array.prototype.indexOf
किसी HTMLCollection
वस्तु पर उपयोग किए जाने वाले अनुकूलन के माध्यम से उजागर होती है ।
parent.childNodes
, बल्किparent.children
। उत्तरार्द्ध केवलElements
विशेषText
नोड्स को छोड़कर, लिस्ट करता है ... यहां दिए गए कुछ उत्तर, जैसे कि उपयोग करpreviousSibling
रहे हैं, सभी चाइल्ड नोड्स का उपयोग करने पर आधारित हैं, जबकि अन्य केवल उन बच्चों से परेशान हैं जोElement
एस ... (!)