2010-04-08 10 views
64

यह कीड़े मुझे कि मैं सिर्फ Firefox 3.6 में भी document.querySelectorAll(...).map(...) ऐसा नहीं कर सकते, और मैं अभी भी एक जवाब नहीं मिल रहा है, तो मैंने सोचा कि मैं इस ब्लॉग से तो सवाल पर पार पद चाहते हैं:document.querySelector क्यों एक असली ऐरे के बजाए एक स्टेटिक नोडलिस्ट लौटाएगा?

http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/

क्या किसी को तकनीकी कारण पता है कि आपको ऐरे क्यों नहीं मिलता है? या क्यों एक StaticNodeList एक ऐरे से इस तरह से वारिस नहीं करता है कि आप map, concat आदि का उपयोग कर सकते हैं?

(btw अगर यह सिर्फ एक समारोह आप चाहते हैं, तो आप NodeList.prototype.map = Array.prototype.map; की तरह कुछ कर सकते हैं ... लेकिन फिर से है, यही कारण है कि इस कार्यक्षमता है (जानबूझकर?) पहले स्थान पर अवरुद्ध?)

+0

असल में भी getElementsByTagName किसी सरणी, लेकिन एक संग्रह वापस नहीं करता है, और अगर आप इसे ऐरे (कॉन्सट इत्यादि जैसी विधियों के साथ) का उपयोग करना चाहते हैं। आपको इस तरह के संग्रह को लूप करके एक ऐरे में परिवर्तित करना होगा और प्रत्येक ele को कॉपी करना होगा एक ऐरे में संग्रह का उल्लेख। किसी ने कभी इसके बारे में शिकायत नहीं की। –

उत्तर

54

मेरा मानना ​​है कि यह W3C के एक दार्शनिक निर्णय किया जाना है। डब्ल्यू 3 सी डोम [spec] का डिज़ाइन जावास्क्रिप्ट के डिजाइन के लिए काफी ऑर्थोगोनल है, क्योंकि डीओएम का मतलब है प्लेटफार्म और भाषा तटस्थ होना।

निर्णय की तरह "getElementsByFoo() रिटर्न एक आदेश दिया NodeList" या "querySelectorAll() रिटर्न एक StaticNodeList" ताकि कार्यान्वयन भाषा पर निर्भर कार्यान्वयन के आधार पर अपने दिए गए डेटा संरचना संरेखित बारे में चिंता करने की जरूरत नहीं है बहुत ज्यादा जानबूझकर कर रहे हैं, (जैसे .map किया जा रहा है जावास्क्रिप्ट और रूबी में Arrays पर उपलब्ध है, लेकिन सी # में सूची पर उपलब्ध नहीं है)।

W3C उद्देश्य कम: वे कहूँगा एक NodeList एक readonly .length property of type unsigned long को शामिल करना चाहिए, क्योंकि वे हर कार्यान्वयन कर सकते हैं कम से कम समर्थन कि विश्वास करते हैं, लेकिन वे स्पष्ट रूप से कहते हैं कि नहीं होगा कि [] सूचकांक ऑपरेटर प्राप्त करने का समर्थन करने के लिए अतिभारित किया जाना चाहिए स्थितित्मक तत्व, क्योंकि वे कुछ खराब छोटी भाषा को छेड़छाड़ नहीं करना चाहते हैं जो getElementsByFoo() को कार्यान्वित करना चाहता है लेकिन ऑपरेटर ओवरलोडिंग का समर्थन नहीं कर सकता है। यह एक प्रचलित दर्शन है जो पूरे नमूने में मौजूद है।

जॉन Resig जो he adds को voiced a similar option तुम्हारा के रूप में, है:

मेरे तर्क इतना है कि NodeIterator नहीं है नहीं है बहुत डोम की तरह यह है कि यह बहुत जावास्क्रिप्ट की तरह नहीं है। यह सुविधाओं जावास्क्रिप्ट भाषा में मौजूद फायदा नहीं उठाता है और अपनी क्षमता का सबसे अच्छा करने के लिए उन्हें का उपयोग करें ...

मैं सहानुभूति कुछ हद तक है। यदि डीओएम विशेष रूप से जावास्क्रिप्ट सुविधाओं के साथ लिखा गया था तो यह बहुत कम अजीब और उपयोग करने के लिए अधिक सहज होगा। साथ ही मैं डब्ल्यू 3 सी के डिजाइन निर्णयों को समझता हूं।

+0

में querySelectorAll() का समर्थन करता है धन्यवाद, जो मुझे स्थिति की समझ में मदद करता है। – Kev

+0

@ केव: मैंने उस ब्लॉग आलेख पृष्ठ पर आपकी टिप्पणी देखी है कि आप 'StaticNodeList' को सरणी में परिवर्तित करने के बारे में कैसे पूछेंगे। मैं @ mck89 के उत्तर को 'नोडलिस्ट'/'स्टेटिक नोडलिस्ट 'को देशी एरे में परिवर्तित करने के तरीके के रूप में समर्थन दूंगा, लेकिन यह जेस्क्रिप्ट त्रुटि के साथ आईई (8 ओबीवी) में विफल हो जाएगा, क्योंकि उन वस्तुओं को होस्ट किया गया है /" विशेष " । –

+0

सच है, यही कारण है कि मैंने उसे ऊपर उठाया। हालांकि किसी और ने अपना +1 रद्द कर दिया है। होस्टेड/विशेष द्वारा आपका क्या मतलब है? – Kev

34

मैं नहीं जानता यह एक सरणी के बजाय नोड सूची क्यों देता है, शायद क्योंकि GetElementsByTagName की तरह यह परिणाम अपडेट करेगा जब आप DOM को अपडेट करते हैं। वैसे भी एक बहुत ही सरल विधि एक सरल सरणी में है कि परिणाम को बदलने के लिए है:

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

और फिर आप कर सकते हैं:

Array.prototype.slice.call(document.querySelectorAll(...)).map(...); 
+3

असल में यह परिणाम अपडेट नहीं करता है जब आप DOM को अपडेट करते हैं - इसलिए 'स्थिर'। परिणाम को अपडेट करने के लिए आपको मैन्युअल रूप से qSA को कॉल करना होगा। हालांकि 'स्लाइस' लाइन के लिए +1। – Kev

+0

हाँ, जैसे केवी ने कहा: qSA परिणामसेट स्थिर है, getElementsByTagName() परिणाम गतिशील है। –

+1

यह यानी 8 सुरक्षित है? – SuperUberDuper

9

बस क्या क्रीसेंट कहा में जोड़ने के लिए,

अगर यह सिर्फ एक समारोह आप चाहते हैं, तो आप NodeList.prototype.map = Array.prototype.map

डॉन की तरह कुछ कर सकता है यह मत करो! यह काम करने की गारंटी नहीं है।

नहीं जावास्क्रिप्ट या डोम/बीओएम मानक निर्दिष्ट करता है कि NodeList निर्माता-समारोह भी एक वैश्विक/window संपत्ति के रूप में मौजूद है, या NodeListquerySelectorAll द्वारा दिया इसे से प्राप्त कर लेंगे कि, या अपने प्रोटोटाइप लिखने योग्य है कि, या कि समारोह Array.prototype.map वास्तव में एक नोडलिस्ट पर काम करेगा।

एक नोडलिस्ट को 'होस्ट ऑब्जेक्ट' (और आईई और कुछ पुराने ब्राउज़र में) होने की अनुमति है। Array विधियों को किसी भी जावास्क्रिप्ट 'मूल ऑब्जेक्ट' पर संचालित करने की अनुमति के रूप में परिभाषित किया गया है जो संख्यात्मक और length गुणों का खुलासा करता है, लेकिन उन्हें होस्ट ऑब्जेक्ट्स (और IE में, वे नहीं) पर काम करने की आवश्यकता नहीं है।

यह कष्टप्रद है कि आपको डोम सूचियों पर सभी सरणी विधियां नहीं मिलती हैं (उनमें से सभी, न केवल स्टेटिक नोडलिस्ट), लेकिन इसके चारों ओर कोई विश्वसनीय तरीका नहीं है।

Array.fromList= function(list) { 
    var array= new Array(list.length); 
    for (var i= 0, n= list.length; i<n; i++) 
     array[i]= list[i]; 
    return array; 
}; 

Array.fromList(element.childNodes).forEach(function() { 
    ... 
}); 
+0

शूट करें, मैंने इसके बारे में नहीं सोचा था। धन्यवाद! – Kev

+0

मैं +1 से सहमत हूं। बस एक टिप्पणी, मुझे लगता है कि "var array = new Array (list.length)" के बजाय "var array = []" कर रहा है "wouild कोड को भी छोटा बना देता है। लेकिन मुझे दिलचस्पी है यदि आपको पता है कि ऐसा करने में कोई समस्या हो सकती है। –

+0

@ मार्कोडेमायो: नहीं, कोई समस्या नहीं। 'नया ऐरे (एन)' सिर्फ जेएस टेरप को संकेत देता है कि सरणी कितनी देर तक खत्म हो जाएगी। इससे पहले उस स्थान की आवंटन को आवंटित करने की अनुमति मिल सकती है, जो संभावित रूप से एक गतिशील परिणामस्वरूप होगा क्योंकि सरणी बढ़ने के साथ ही कुछ स्मृति पुनर्वितरणों से बचा जा सकता है। मुझे नहीं पता कि यह वास्तव में आधुनिक ब्राउज़र में मदद करता है हालांकि ... मुझे मापने की संभावना नहीं है। – bobince

70

आप ES2015 (ES6) का उपयोग कर सकते spread operator:

[...document.querySelectorAll('div')]

मदों की सरणी के लिए StaticNodeList में परिवर्तित कर देंगे आप हर डोम सूची आप मैन्युअल रूप से किसी सरणी के लिए वापस पाने के कन्वर्ट करने के लिए होगा।

यहां इसका उपयोग करने के तरीके पर एक उदाहरण दिया गया है।

[...document.querySelectorAll('div')].map(x => console.log(x.innerHTML))
<div>Text 1</div> 
 
<div>Text 2</div>

0

मुझे लगता है कि आप बस निम्न कर सकते हैं

Array.prototype.map.call(document.querySelectorAll(...), function(...){...}); 

यह मेरे लिए एकदम सही काम करता है

संबंधित मुद्दे