जावास्क्रिप्ट NodeList को Array में बदलने का सबसे तेज़ तरीका?


251

पहले पूछे गए सवालों के जवाब में कहा गया था कि यह सबसे तेज़ तरीका था:

//nl is a NodeList
var arr = Array.prototype.slice.call(nl);

अपने ब्राउज़र पर बेंचमार्किंग में मैंने पाया है कि यह इससे 3 गुना अधिक धीमा है:

var arr = [];
for(var i = 0, n; n = nl[i]; ++i) arr.push(n);

वे दोनों एक ही आउटपुट का उत्पादन करते हैं, लेकिन मुझे यह विश्वास करना मुश्किल है कि मेरा दूसरा संस्करण सबसे तेज़ संभव तरीका है, खासकर जब से लोगों ने अन्यथा यहां कहा है।

क्या यह मेरे ब्राउज़र में एक क्रोम है (क्रोमियम 6)? या वहाँ एक तेज़ तरीका है?

संपादित करें: जो कोई भी परवाह करता है, उसके लिए मैं निम्नलिखित पर गया (जो मेरे द्वारा परीक्षण किए गए प्रत्येक ब्राउज़र में सबसे तेज़ प्रतीत होता है):

//nl is a NodeList
var l = []; // Will hold the array of Node's
for(var i = 0, ll = nl.length; i != ll; l.push(nl[i++]));

EDIT2: मैं एक और भी तेजी से रास्ता मिल गया

// nl is the nodelist
var arr = [];
for(var i = nl.length; i--; arr.unshift(nl[i]));

2
arr[arr.length] = nl[i];इससे तेज हो सकता है arr.push(nl[i]);क्योंकि यह फ़ंक्शन कॉल से बचता है।
Luc125

9
यह jsPerf पृष्ठ इस पृष्ठ के सभी उत्तरों पर नज़र रख रहा है: jsperf.com/nodelist-to-array/27
pilau

कृपया ध्यान दें कि "EDIT2: I ने एक तेज़ तरीका पाया" IE8 पर 92% धीमा है।
कैमिलो मार्टिन

2
जब से तुम पहले से ही पता पता है कि तुम कितने नोड्स है:var i = nl.length, arr = new Array(i); for(; i--; arr[i] = nl[i]);
एमईएमएस

@ Luc125 यह ब्राउज़र पर निर्भर करता है, चूंकि पुश कार्यान्वयन को अनुकूलित किया जा सकता है, मैं क्रोम के बारे में सोच रहा हूं क्योंकि v8 इस तरह के सामान के साथ अच्छा है।
अक्साल्डुच

जवाबों:


197

दूसरा ब्राउज़र कुछ ब्राउज़र में तेज़ हो जाता है, लेकिन मुख्य बिंदु यह है कि आपको इसका उपयोग करना होगा क्योंकि पहले वाला अभी क्रॉस-ब्राउज़र नहीं है। भले ही द टाइम्स वे आर-चेंजिन हैं

@कांगैक्स ( IE 9 पूर्वावलोकन )

Array.prototyp.slice अब कुछ होस्ट ऑब्जेक्ट्स (जैसे NodeList's) को सरणियों में परिवर्तित कर सकता है - कुछ जो आधुनिक ब्राउज़र के अधिकांश लोग काफी समय से कर पा रहे हैं।

उदाहरण:

Array.prototype.slice.call(document.childNodes);

??? दोनों क्रॉस-ब्राउज़र संगत हैं - जावास्क्रिप्ट (कम से कम अगर यह दावा करता है कि ECMAscript युक्ति संगत है) तो जावास्क्रिप्ट है; ऐरे, प्रोटोटाइप, स्लाइस और कॉल सभी मुख्य भाषा + ऑब्जेक्ट प्रकार की विशेषताएं हैं।
जेसन एस

6
लेकिन वे IE में NodeLists पर इस्तेमाल नहीं किया जा सकता (मुझे पता है कि यह बेकार है, लेकिन हे मेरे अद्यतन देखें)
gblazex

9
क्योंकि नोडलिस्ट भाषा का हिस्सा नहीं हैं, वे DOM API का हिस्सा हैं, जिसे विशेष रूप से IE में छोटी गाड़ी / अप्रत्याशित के रूप में जाना जाता है
gblazex

3
यदि आप IE8 को खाते में लेते हैं, तो Array.prototype.slice क्रॉस ब्राउज़र नहीं है।
लाजोस मेस्सरोस

1
हां, यही मेरा जवाब मूल रूप से :) के बारे में था, हालांकि यह आज (2015) की तुलना में 2010 में अधिक प्रासंगिक था।
gblazex

224

ईएस 6 के साथ, अब हमारे पास नोडेलिस्ट से एक एरे बनाने का एक सरल तरीका है: Array.from()फ़ंक्शन।

// nl is a NodeList
let myArray = Array.from(nl)

यह नई ES6 विधि दूसरों के लिए गति की तुलना में ऊपर उल्लेखित है?
user5508297

10
@ user5508297 स्लाइस कॉल ट्रिक से बेहतर है। छोरों के लिए की तुलना में धीमी है, लेकिन यह बिल्कुल नहीं है कि हम इसे ट्रावर्स किए बिना एक सरणी रखना चाहते हैं। और वाक्यविन्यास सुंदर, सरल और याद रखने में आसान है!
15

Array.from के बारे में अच्छी बात यह है कि आप मानचित्र तर्क का उपयोग कर सकते हैं:console.log(Array.from([1, 2, 3], x => x + x)); // expected output: Array [2, 4, 6]
honzajde

103

यहां ES6 स्प्रेड ऑपरेटर का उपयोग करके इसे करने का एक नया तरीका है :

let arr = [...nl];

7
टाइपस्क्रिप्ट में मेरे लिए काम नहीं किया। ERROR TypeError: el.querySelectorAll(...).slice is not a function
अलिर्ज़ा मिरियन


19

कुछ अनुकूलन:

  • एक चर में NodeList की लंबाई को बचाएं
  • स्पष्ट रूप से सेट करने से पहले नए सरणी की लंबाई निर्धारित करें।
  • धक्का देने या न हटाने के बजाय सूचकांकों का उपयोग करें।

कोड ( jsPerf ):

var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
 arr[i] = nl[i];
}

आप सरणी बनाने के बजाय ऐरे (लंबाई) का उपयोग करके थोड़ा अलग समय दाढ़ी कर सकते हैं और फिर इसे अलग-अलग आकार दे सकते हैं। यदि आप फिर ऐरो का उपयोग करते हैं, तो ऐरे और उसकी लंबाई को घोषित करने के लिए, लूप के अंदर एक लेट के साथ, यह उपरोक्त विधि की तुलना में लगभग 1.5% तेजी से समाप्त होता है: कॉस्ट ए = ऐरे (एलएल.लोमिट्री), सी = ए.एल. for (let b = 0; b <c; b ++) {a [b] = nl [b]; } jsperf.com/nodelist-to-array/93
ब्रायनफ्रेंड

15

परिणाम पूरी तरह से ब्राउज़र पर निर्भर करेगा, उद्देश्यपूर्ण निर्णय देने के लिए, हमें कुछ प्रदर्शन परीक्षण करने होंगे, यहाँ कुछ परिणाम दिए गए हैं, आप उन्हें यहाँ चला सकते हैं :

क्रोम 6:

फ़ायरफ़ॉक्स 3.6:

फ़ायरफ़ॉक्स 4.0b2:

सफारी 5:

IE9 प्लेटफ़ॉर्म पूर्वावलोकन 3:


1
मुझे आश्चर्य है कि लूप के लिए रिवर्स कैसे इन के खिलाफ रखती है? for (var i=o.length; i--;)... क्या इन परीक्षणों में 'लूप के लिए' हर पुनरावृत्ति पर लंबाई की संपत्ति का मूल्यांकन करता है?
डग नबबिट

14

सबसे तेज़ और क्रॉस ब्राउज़र है

for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);

जैसा कि मैंने तुलना की है

http://jsbin.com/oqeda/98/edit

* विचार के लिए @CMS को धन्यवाद!

क्रोमियम (Google Chrome के समान) फ़ायरफ़ॉक्स ओपेरा


1
लिंक गलत प्रतीत होता है, आपके द्वारा बताए गए परीक्षण को शामिल करने के लिए 89 के बजाय 91 होना चाहिए। और 98 सबसे पूरा लगता है।
यारोस्लाव याकोवले

9

ES6 में आप या तो उपयोग कर सकते हैं:

  • Array.from

    let array = Array.from(nodelist)

  • फैला हुआ संचालक

    let array = [...nodelist]


पिछले उत्तरों में जो पहले से लिखा गया है, उसमें कुछ भी नया न जोड़ें।
स्टीफन बेकर

7
NodeList.prototype.forEach = Array.prototype.forEach;

अब आप document.querySelectorAll ('div') कर सकते हैं। forEach (function () ...)


अच्छा विचार, धन्यवाद @ जॉन! हालांकि, NodeListकाम नहीं कर रहा है, लेकिन Objectहै: Object.prototype.forEach = Array.prototype.forEach; document.getElementsByTagName("img").forEach(function(img) { alert(img.src); });
इयान कैंपबेल

3
Object.prototype का उपयोग न करें: यह JQuery और शब्दकोश शाब्दिक वाक्यविन्यास जैसी चीजों की एक टन को तोड़ता है।
नैट सिमर

यकीन है, देशी निर्मित कार्यों का विस्तार करने से बचें।
रोलैंड

5

तेज और छोटा:

// nl is the nodelist
var a=[], l=nl.length>>>0;
for( ; l--; a[l]=nl[l] );

3
क्यों >>>0? और लूप के लिए पहले हिस्से पर असाइनमेंट क्यों नहीं लगाए गए?
कैमिलो मार्टिन

5
इसके अलावा, यह छोटी गाड़ी है। जब lहै 0, लूप समाप्त हो जाएगा, इसलिए 0वें तत्व की प्रतिलिपि नहीं बनाई जाएगी (अनुक्रमणिका में एक तत्व है 0)
कैमिलो मार्टिन

1
इस जवाब से प्यार है, लेकिन ... जो कोई सोच रहा है: >>> हो सकता है यहाँ आवश्यक नहीं हो लेकिन सरणी कल्पना करने के लिए nodelist की दूरी पालन करता है की गारंटी करने के लिए किया जाता है; यह सुनिश्चित करता है कि यह एक अहस्ताक्षरित 32-बिट पूर्णांक है। इसे यहाँ देखें ecma-international.org/ecma-262/5.1/#sec-15.4 यदि आपको अपठनीय कोड पसंद है, तो इस विधि का उपयोग @ CamiloMartin के सुझावों के साथ करें!
टोड

@CamiloMartin के जवाब में - 'परिवर्तनशील होर्डिंग' के कारण लूप varके पहले भाग के अंदर रखना जोखिम भरा है forvarफ़ंक्शन के शीर्ष पर 'फहराया' की घोषणा की जाएगी, भले ही varलाइन कहीं नीचे दिखाई दे, और इससे साइड इफेक्ट्स हो सकते हैं जो कोड अनुक्रम से स्पष्ट नहीं हैं। उदाहरण के लिए एक ही समारोह में कुछ कोड उत्पन्न हो रही से पहले पाश के लिए हो सकता है निर्भर पर aऔर lअघोषित जा रहा है। इसलिए अधिक से अधिक विधेय के लिए, फ़ंक्शन के शीर्ष पर (या यदि ईएस 6 पर, का उपयोग करें constया letइसके बजाय, जो लहरा नहीं करते हैं) के ऊपर अपने संस्करण घोषित करें ।
brennanyoung

3

यहाँ इस ब्लॉग पोस्ट को देखें जो एक ही चीज़ के बारे में बात करता है। मैं जो इकट्ठा करता हूं, उससे अतिरिक्त समय का दायरा श्रृंखला के साथ चलना हो सकता है।


दिलचस्प। मैंने अभी कुछ इसी तरह के परीक्षण किए थे और फ़ायरफ़ॉक्स 3.6.3 ने इसे किसी भी तरह से गति में कोई वृद्धि नहीं दिखाई है, जबकि ओपेरा 10.6 में 20% की वृद्धि हुई है और क्रोम 6 में 230% (!) वृद्धि हुई है जो इसे मैन्युअल रूप से पुश-पुश तरीके से कर रहा है।
जयराज j

@ jairajs89 काफी अजीब है। ऐसा प्रतीत होता है कि Array.prototype.sliceब्राउज़र-निर्भर है। मुझे आश्चर्य है कि प्रत्येक ब्राउज़र किस एल्गोरिथ्म का उपयोग कर रहा है।
विविन पालीथ

3

यह वह फ़ंक्शन है जिसका उपयोग मैं अपने JS में करता हूं:

function toArray(nl) {
    for(var a=[], l=nl.length; l--; a[l]=nl[l]);
    return a;
}

1

इस पोस्टिंग की तारीख के रूप में अपडेट किए गए चार्ट ("अज्ञात प्लेटफ़ॉर्म" चार्ट इंटरनेट एक्सप्लोरर 11.15.16299.0 है):

सफारी 11.1.2 फ़ायरफ़ॉक्स 61.0 क्रोम 68.0.3440.75 इंटरनेट एक्सप्लोरर 11.15.16299.0

इन परिणामों से, ऐसा लगता है कि उपदेश 1 विधि सबसे सुरक्षित क्रॉस-ब्राउज़र शर्त है।


1

मान लें nodeList = document.querySelectorAll("div"), यह nodelistसरणी में कनवर्ट करने का संक्षिप्त रूप है ।

var nodeArray = [].slice.call(nodeList);

मुझे इसका उपयोग यहाँ देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.