HTMLCollection को Array में बदलने का सबसे कारगर तरीका


391

क्या HTML संग्रह को एक Array में बदलने का एक अधिक कुशल तरीका है, जो उक्त संग्रह की सामग्री के माध्यम से पुनरावृत्ति करने के अलावा और प्रत्येक आइटम को एक सरणी में मैन्युअल रूप से धकेलता है?


10
"कुशल" से क्या तात्पर्य है? तो सबसे अच्छा प्रदर्शन, एक के लिए पाश आम तौर पर तेजी से है Array.prototype.slice । एक पाश भी ब्राउज़रों (यानी सभी) की एक व्यापक विविधता में काम करता है, इसलिए उन मापदंडों के आधार पर यह है "सबसे कारगर तरीका"। और यह बहुत कम कोड है: for (var a=[], i=collection.length; i;) a[--i] = collection[i];इसलिए "कोन" का बहुत कुछ नहीं है :-)
RobG

@RobG धन्यवाद - अगर मैं कर सकता तो मैं आपको + 59k देता! ;-)
स्लैशबैक

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

मैंने एक jsperf टेस्ट बनाया जो दोनों तरीकों को देखता है जिसमें @harpo का उल्लेख किया गया है और साथ ही प्रदर्शन के लिए jquery टेस्ट भी। मैंने पाया है कि javascript दोनों विधियों की तुलना में jquery थोड़ी धीमी है और js परीक्षण मामलों के बीच शीर्ष प्रदर्शन भिन्न होता है। क्रोम 59.0.3071 / मैक ओएस एक्स 10.12.5 का उपयोग करना पसंद करते हैं Array.prototype.slice.callऔर बहादुर (क्रोम 59.0.3071 पर आधारित) वस्तुतः कई रनवे पर दो जावास्क्रिप्ट परीक्षणों के बीच कोई अंतर नहीं है। देखें jsperf.com/htmlcollection-array-vs-jquery-children
NuclearPeon

jsben.ch/h2IFA => ऐसा करने के सबसे सामान्य तरीकों के लिए प्रदर्शन परीक्षण
एस्केपनेट

जवाबों:


696
var arr = Array.prototype.slice.call( htmlCollection )

"मूल" कोड का उपयोग करके समान प्रभाव होगा।

संपादित करें

चूंकि यह बहुत सारे विचार प्राप्त करता है, ध्यान दें (प्रति @ oriol की टिप्पणी) कि निम्नलिखित अधिक संक्षिप्त अभिव्यक्ति प्रभावी रूप से समतुल्य है:

var arr = [].slice.call(htmlCollection);

लेकिन @ JussiR की टिप्पणी पर ध्यान दें, "क्रिया" रूप के विपरीत, यह प्रक्रिया में एक खाली, अप्रयुक्त और वास्तव में अनुपयोगी सरणी उदाहरण बनाता है। इस बारे में क्या कंपाइलर प्रोग्रामर के केन के बाहर हैं।

संपादित करें

ECMAScript 2015 (ES 6) के बाद से Array.from भी है :

var arr = Array.from(htmlCollection);

संपादित करें

ECMAScript 2015 प्रसार ऑपरेटर भी प्रदान करता है , जो कार्यात्मक रूप से इसके बराबर है Array.from(हालांकि ध्यान दें कि Array.fromदूसरे तर्क के रूप में मैपिंग फ़ंक्शन का समर्थन करता है)।

var arr = [...htmlCollection];

मैंने पुष्टि की है कि उपरोक्त दोनों काम करते हैं NodeList

उल्लिखित विधियों के लिए एक प्रदर्शन की तुलना: http://jsben.ch/h2IFA


7
यह IE6 में विफल रहता है।
हीथ बॉर्डर

29
शॉर्टकट [].slice.call(htmlCollection)भी काम करता है।
ओरोल

1
@ क्रिसनील्सन हां मुझे उस पर गलत जानकारी दी गई थी। चारों ओर फैलने के लिए क्षमा करें। मुझे नहीं पता था कि मैंने कहा था कि यहाँ भी। भ्रम से बचने के लिए टिप्पणी को हटा दिया गया था लेकिन संदर्भ के लिए मैंने कहीं पढ़ा था (या गलत तरीके से) कि HTMLCollection को कम करके इसे एक सरणी और एक संग्रह दोनों की तरह व्यवहार किया। पूरी तरह से गलत है।
एरिक रिपेन

3
[] .Slice शॉर्टकट समतुल्य नहीं है क्योंकि यह अप्रयुक्त खाली सरणी उदाहरण भी बनाता है। सुनिश्चित नहीं है कि कंपाइलर इसे दूर अनुकूलित करने में सक्षम हैं, हालांकि।
जस्सीआर

3
Array.from, अर्थात् from, IE11 द्वारा समर्थित नहीं है।
फ्रैंक कॉनिजन

86

यकीन नहीं है कि यह सबसे कुशल है, लेकिन एक संक्षिप्त ES6 वाक्यविन्यास हो सकता है:

let arry = [...htmlCollection] 

संपादित करें: एक और एक, Chris_F टिप्पणी से:

let arry = Array.from(htmlCollection)

9
इसके अतिरिक्त, ES6 जोड़ता हैArray.from()
Chris_F

4
पहले एक के लिए बाहर देखो, वहाँ एक सूक्ष्म बग है जब कोलाहल के साथ स्थानांतरित कर रहा है जहाँ [... htmlCollection] htmlCollection के साथ एक सरणी लौटाएगा क्योंकि यह केवल तत्व है।
मार्सेल एम।

3
सरणी प्रसार ऑपरेटर htmlCollection पर काम नहीं करता है। यह केवल NodeList पर लागू होता है।
बॉबी

1
Array.from, अर्थात् from, IE11 द्वारा समर्थित नहीं है।
फ्रैंक कॉनिजन

बेंचमार्क लगता है कि प्रसार ऑपरेटर इन 2 से तेज है।
RedSparr0w

20

मैंने Array.prototypeसामान्य रूप से विधियों को प्राप्त करने का एक अधिक संक्षिप्त तरीका देखा जो ठीक वैसे ही काम करता है। किसी HTMLCollectionवस्तु को किसी वस्तु में बदलने से Arrayनीचे दिखाया गया है:

[] .slice.call (आपका HTMLCollectionObject);

और, जैसा कि टिप्पणियों में बताया गया है, पुराने ब्राउज़र जैसे IE7 और पहले के लिए, आपको बस एक संगतता फ़ंक्शन का उपयोग करना होगा, जैसे:

function toArray(x) {
    for(var i = 0, a = []; i < x.length; i++)
        a.push(x[i]);

    return a
}

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन मुझे लगा कि स्वीकृत उत्तर थोड़ा अधूरा था; इसलिए मैंने सोचा कि मैं इसे FWIW से बाहर फेंक दूंगा।


6

एक क्रॉस ब्राउज़र कार्यान्वयन के लिए, मैं आपको प्रोटोटाइप.जेएस $A फ़ंक्शन को देखना चाहता हूं

1.6.1 से कॉपी किया गया :

function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

यह Array.prototype.sliceशायद उपयोग नहीं करता है क्योंकि यह हर ब्राउज़र पर उपलब्ध नहीं है। मुझे डर है कि प्रदर्शन बहुत खराब है क्योंकि पीछे गिरने पर एक जावास्क्रिप्ट लूप है iterable


2
ओपी ने "उक्त संग्रह की सामग्री के माध्यम से पुनरावृत्ति और मैन्युअल रूप से प्रत्येक आइटम को एक सरणी में धकेलने" के अलावा अन्य तरीके के लिए कहा, लेकिन यह वही है जो $Aफ़ंक्शन ज्यादातर समय करता है।
Luc125

1
मुझे लगता है कि जिस बिंदु को मैं बनाने की कोशिश कर रहा था, वह यह है कि ऐसा करने का एक अच्छा तरीका नहीं है, प्रोटोटाइप.जेएस कोड दिखाता है कि आप एक 'एअरे' विधि की तलाश कर सकते हैं लेकिन यह असफलता सबसे सुरक्षित मार्ग है
गैरेथ डेविस

1
यह विरल सरणियों में नए, अपरिभाषित सदस्यों का निर्माण करेगा। असाइनमेंट से पहले hasOwnProperty टेस्ट होना चाहिए ।
रॉब

3

यह मेरा व्यक्तिगत समाधान है, यहाँ की जानकारी (इस सूत्र) पर आधारित है:

var Divs = new Array();    
var Elemns = document.getElementsByClassName("divisao");
    try {
        Divs = Elemns.prototype.slice.call(Elemns);
    } catch(e) {
        Divs = $A(Elemns);
    }

गैरेथ डेविस ने अपनी पोस्ट में $ A का वर्णन कहाँ किया था:

function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

यदि ब्राउज़र सबसे अच्छा तरीका का समर्थन करता है, ठीक है, अन्यथा क्रॉस ब्राउज़र का उपयोग करेगा।


सामान्य तौर पर, मैं नियंत्रण प्रवाह को प्रबंधित करने के लिए एक कुशल तरीका होने की कोशिश / पकड़ की उम्मीद नहीं करता हूं। आप देख सकते हैं कि फ़ंक्शन पहले मौजूद है, तो या तो एक या दूसरे को थोड़ा सस्ता चलाएं।
पैट्रिक

2
गैरेथ डेविस के जवाब के साथ, यह विरल सरणियों में नए, अपरिभाषित सदस्य बनाता है, इसलिए [,,]बन जाता है [undefined, undefined]
रॉब

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

3

यह पहले के IE संस्करणों सहित सभी ब्राउज़रों में काम करता है।

var arr = [];
[].push.apply(arr, htmlCollection);

चूंकि jsperf अभी भी नीचे है, इसलिए यहां एक jsfiddle है जो विभिन्न तरीकों के प्रदर्शन की तुलना करता है। https://jsfiddle.net/qw9qf48j/


कोशिशvar args = (htmlCollection.length === 1 ? [htmlCollection[0]] : Array.apply(null, htmlCollection));
शाहर शोकानी

3

सरणी-प्रकार को सरणी में बदलने के लिए हम jQuery का उपयोग कर सकते हैं makeArray:

मेकअरे: एक सरणी जैसी वस्तु को एक सच्चे जावास्क्रिप्ट सरणी में परिवर्तित करें।

उपयोग:

var domArray = jQuery.makeArray(htmlCollection);

कुछ ज्यादा:

यदि आप सरणी ऑब्जेक्ट के संदर्भ में नहीं रखना चाहते हैं (ज्यादातर HTMLCollections गतिशील रूप से बदलते हैं तो उन्हें किसी अन्य सरणी में कॉपी करने के लिए बेहतर है, यह उदाहरण प्रदर्शन पर ध्यान देता है:

var domDataLength = domData.length //Better performance, no need to calculate every iteration the domArray length
var resultArray = new Array(domDataLength) // Since we know the length its improves the performance to declare the result array from the beginning.

for (var i = 0 ; i < domDataLength ; i++) {
    resultArray[i] = domArray[i]; //Since we already declared the resultArray we can not make use of the more expensive push method.
}

सरणी-जैसा क्या है?

HTMLCollection एक "array-like"ऑब्जेक्ट है, सरणी जैसी ऑब्जेक्ट सरणी के ऑब्जेक्ट के समान हैं, लेकिन इसकी कार्यात्मक परिभाषा के बहुत सारे लापता हैं:

सरणी जैसी वस्तुएं सरणियों की तरह दिखती हैं। उनके पास विभिन्न संख्या वाले तत्व और एक लंबी संपत्ति है। लेकिन यही वह जगह है जहां समानता बंद हो जाती है। ऐरे की तरह की वस्तुओं में एरे का कोई कार्य नहीं होता है, और इसके लिए लूप भी काम नहीं करते हैं!

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