𝗥𝗲𝘀𝘂𝗹𝘁𝘀 𝗥𝗲𝘀𝘂𝗹𝘁𝘀 𝗥𝗲𝘀𝘂𝗹𝘁𝘀
तथ्यों के लिए, jsperf में एक प्रदर्शन परीक्षण और कंसोल में कुछ चीजों की जांच की जाती है। शोध के लिए, irt.org वेबसाइट का उपयोग किया जाता है। नीचे इन सभी स्रोतों का एक संग्रह है, साथ ही नीचे एक उदाहरण समारोह भी रखा गया है।
╔═══════════════╦══════╦═════════════════╦════════ ═══════╦═════════╦══════════╗
║ विधि ║Concat║slice और push.apply app push.apply x2 ║ ForLoop ║Spread ║
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║ mOps / Sec 9179 ║104 ║ 76 ║ 81 O28 /
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║ विरल सरणियों ESYES! ║ केवल कटा हुआ ║ नहीं ║ शायद 2 ║ कोई slic
║ विरल रखा गया ║ ║array (प्रथम arg) se se sp se
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
║ समर्थन ║MSIE 4║MSIE 5.5 5.5 MSIE 5.5 4 MSIE 4 dEdge 12 ║
║ ( स्रोत ) NNNav 4║NNav 4.06 av NNav 4.06 N NNav 3 av MSIE NNav ║
╠═══════════════╬══════╬═════════════════╬════════ ═══════╬═════════╬══════════╣
Lyअरे की तरह हरकतें ║ केवल ║ हां धकेल दिया! ║ हाँ! ║यदि ║ है
║like एक सरणी ║ rayarray (दूसरा arg) ║ ║ atoriterator 1 ║
╚═══════════════╩══════╩═════════════════╩════════ ═══════╩═════════╩══════════╝
1 यदि सरणी जैसी ऑब्जेक्ट में Symbol.iterator गुण नहीं है , तो कोशिश कर रहा है
फैलाने के लिए यह एक अपवाद फेंक देगा।
2 कोड पर निर्भर करता है। निम्न उदाहरण कोड "YES" विरलता को संरक्षित करता है।
function mergeCopyTogether(inputOne, inputTwo){
var oneLen = inputOne.length, twoLen = inputTwo.length;
var newArr = [], newLen = newArr.length = oneLen + twoLen;
for (var i=0, tmp=inputOne[0]; i !== oneLen; ++i) {
tmp = inputOne[i];
if (tmp !== undefined || inputOne.hasOwnProperty(i)) newArr[i] = tmp;
}
for (var two=0; i !== newLen; ++i, ++two) {
tmp = inputTwo[two];
if (tmp !== undefined || inputTwo.hasOwnProperty(two)) newArr[i] = tmp;
}
return newArr;
}
जैसा कि ऊपर देखा गया है, मैं तर्क दूंगा कि कॉनैट लगभग हमेशा प्रदर्शन के लिए जाने का तरीका है और अतिरिक्त सरणियों की दुर्लभता को बनाए रखने की क्षमता है। फिर, सरणी-पसंद (जैसे DOMNodeLists जैसे document.body.children
) के लिए, मैं लूप के लिए उपयोग करने की सलाह दूंगा क्योंकि यह 2 सबसे अधिक प्रदर्शन करने वाला और एकमात्र अन्य तरीका है जो विरल सरणियों को बनाए रखता है। नीचे, हम जल्दी से खत्म हो जाएगा और विरल सरणियों और भ्रम को स्पष्ट करने के लिए सरणी-पसंद से क्या मतलब है।
𝗧𝗵𝗲 𝗧𝗵𝗲
सबसे पहले, कुछ लोग सोच सकते हैं कि यह एक अस्थायी है और ब्राउज़र विक्रेताओं को अंततः Array.prototyp.push का अनुकूलन करने के लिए चारों ओर ले जाएगा और Array.prototyp.concat को हरा देने के लिए पर्याप्त तेज़ होगा। गलत! Array.prototype.concat हमेशा तेज़ होगा (सिद्धांत में कम से कम) क्योंकि यह डेटा पर एक साधारण कॉपी-एन-पेस्ट है। नीचे एक सरलीकृत प्रेरक-दृश्य आरेख है, जिसमें 32-बिट सरणी कार्यान्वयन कैसा दिख सकता है (कृपया ध्यान दें कि वास्तविक कार्यान्वयन एक बहुत अधिक जटिल हैं)
बाइट te यहां डेटा
═════╬═══════════
0x00 x int nonNumericPropertiesLength = 0x00000000
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 x इंट लंबाई = 0x00000001
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 x int valueIndex = 0x00000000
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 x int valueType = JS_PRIMITIVE_NUMBER
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
0x00 x uintptr_t valuePointer = 0x38d9eb60 (या जहाँ भी यह मेमोरी में है)
0x01 ║ ibid
0x02 ║ ibid
0x03 ║ ibid
जैसा कि ऊपर देखा गया है, आपको कुछ ऐसा करने की ज़रूरत है जो बाइट के लिए बाइट को कॉपी करते हुए लगभग उतना ही सरल हो। Array.prototype.push.apply के साथ, यह डेटा पर एक साधारण कॉपी-एन-पेस्ट की तुलना में बहुत अधिक है। ".Apply" को सरणी में प्रत्येक सूचकांक की जांच करनी होगी और इसे Array.prototype.push पर जाने से पहले तर्क के सेट में परिवर्तित करना होगा। फिर, Array.prototype.push को अतिरिक्त रूप से प्रत्येक बार अधिक मेमोरी आवंटित करनी होती है, और (कुछ ब्राउज़र कार्यान्वयनों के लिए) शायद स्पार्सनेस के लिए कुछ पोजीशन-लुकअप डेटा की पुन: गणना भी करें।
इसके बारे में सोचने का एक वैकल्पिक तरीका यह है। स्रोत सरणी एक एक साथ स्टेपल किए गए कागजों का एक बड़ा ढेर है। स्रोत सरणी दो भी कागजात का एक और बड़ा ढेर है। क्या यह आपके लिए तेज़ होगा
- स्टोर पर जाएं, प्रत्येक स्रोत सरणी की प्रतिलिपि के लिए आवश्यक पर्याप्त कागज खरीदें। फिर कॉपी-मशीन के माध्यम से कागज के प्रत्येक स्रोत सरणी स्टैक रखें और परिणामस्वरूप दो प्रतियों को एक साथ स्टेपल करें।
- स्टोर पर जाएं, पहले स्रोत सरणी की एक प्रति के लिए पर्याप्त कागज खरीदें। फिर, स्रोत सरणी को नए पेपर में हाथ से कॉपी करें, किसी भी रिक्त विरल स्पॉट को भरना सुनिश्चित करें। फिर, स्टोर पर वापस जाएं, दूसरे स्रोत सरणी के लिए पर्याप्त पेपर खरीदें। फिर, दूसरे स्रोत सरणी से गुजरें और प्रतिलिपि में कोई रिक्त अंतराल सुनिश्चित करते हुए इसे कॉपी करें। फिर, सभी कॉपी किए गए पेपर्स को एक साथ स्टेपल करें।
उपरोक्त सादृश्य में, विकल्प # 1 Array.prototype.concat का प्रतिनिधित्व करता है, जबकि # 2 Array.prototype.push.apply का प्रतिनिधित्व करता है। आइए हम इसे एक समान JSperf के साथ अलग-अलग परीक्षण करते हैं कि यह एक विरल सरणियों के तरीकों का परीक्षण करता है, न कि ठोस सरणियों का। कोई इसे यहीं पा सकता है ।
इसलिए, मैं अपने मामले को आराम देता हूं कि इस विशेष उपयोग के मामले में प्रदर्शन का भविष्य Array.prototyp.push में नहीं है, बल्कि Array.prototyp.concat में निहित है।
𝗖𝗹𝗮𝗿𝗶𝗳𝗶𝗰𝗮𝘁𝗶𝗼𝗻𝘀
𝗦𝗽𝗮𝗿𝗲 𝗦𝗽𝗮𝗿𝗲
जब सरणी के कुछ सदस्य बस गायब हैं। उदाहरण के लिए:
// This is just as an example. In actual code,
// do not mix different types like this.
var mySparseArray = [];
mySparseArray[0] = "foo";
mySparseArray[10] = undefined;
mySparseArray[11] = {};
mySparseArray[12] = 10;
mySparseArray[17] = "bar";
console.log("Length: ", mySparseArray.length);
console.log("0 in it: ", 0 in mySparseArray);
console.log("arr[0]: ", mySparseArray[0]);
console.log("10 in it: ", 10 in mySparseArray);
console.log("arr[10] ", mySparseArray[10]);
console.log("20 in it: ", 20 in mySparseArray);
console.log("arr[20]: ", mySparseArray[20]);
वैकल्पिक रूप से, जावास्क्रिप्ट आपको अतिरिक्त सरणियों को आसानी से शुरू करने की अनुमति देता है।
var mySparseArray = ["foo",,,,,,,,,,undefined,{},10,,,,,"bar"];
𝗔𝗿𝗿𝗮𝘆-𝗟𝗶𝗸𝗲𝘀
एक सरणी की तरह एक वस्तु कम से कम एक है कि length
संपत्ति है, लेकिन साथ आरंभ नहीं किया गया था new Array
या []
; उदाहरण के लिए, नीचे की वस्तुओं को सरणी की तरह वर्गीकृत किया गया है।
{0: "फू", 1: "बार", लंबाई: 2}
document.body.children
नई Uint8Array (3)
- यह सरणी-जैसा है क्योंकि यह एक (n) (टाइप) सरणी है, लेकिन इसे किसी सरणी में ले जाने से कंस्ट्रक्टर बदल जाता है।
(फ़ंक्शन () {वापसी तर्क}) ()
निरीक्षण करें कि एक विधि का उपयोग करने से क्या होता है जो एरोस-लाइक को स्लाइस की तरह ले जाती है।
var slice = Array.prototype.slice;
// For arrays:
console.log(slice.call(["not an array-like, rather a real array"]));
// For array-likes:
console.log(slice.call({0: "foo", 1: "bar", length:2}));
console.log(slice.call(document.body.children));
console.log(slice.call(new Uint8Array(3)));
console.log(slice.call( function(){return arguments}() ));
- ध्यान दें: प्रदर्शन के कारण फ़ंक्शन तर्कों पर स्लाइस कॉल करना बुरा अभ्यास है।
निरीक्षण करें कि एक विधि का उपयोग करने से क्या होता है जो एरे-कॉर्ट में सरणी-पसंद को कॉनराट की तरह नहीं करता है ।
var empty = [];
// For arrays:
console.log(empty.concat(["not an array-like, rather a real array"]));
// For array-likes:
console.log(empty.concat({0: "foo", 1: "bar", length:2}));
console.log(empty.concat(document.body.children));
console.log(empty.concat(new Uint8Array(3)));
console.log(empty.concat( function(){return arguments}() ));