JavaScript'te, bir NodeList'i bir diziye dönüştürmenin en iyi yolu nedir?


84

DOM yöntemi document.querySelectorAll()(ve birkaç tane daha) bir NodeList.

Listede işlem yapmak için, örneğin kullanarak forEach(), NodeListönce bir Array.

Dönüştürmek için en iyi yolu nedir NodeListbir etmek Array?


1
SorguSelectorAll () işlevinin dönüş değerinin teknik olarak NodeList olarak adlandırıldığını düşünüyorum.
jfriend00

dan MDM "elementList = document.querySelectorAll (seçiciler);"
cc young

1
elementList, değişken adıdır. Aynı sayfa, dönüş değerinin türünün nasıl bir NodeList olduğunu açıklar.
jfriend00

düzeltilmesi için teşekkürler - Söz konusu sabit
genç cc

Yanıtlar:


70

ES6 ile şunları yapabilirsiniz:

const spanList = [...document.querySelectorAll("span")];

1
Bu bana verirType 'NodeListOf<Element>' must have a '[Symbol.iterator]()' method that returns an iterator.ts(2488)
geri arama

Merhaba @callback, bu TypeScript ile ilgili bir hata gibi görünüyor. Tsconfig dosyanızın lib dizisine "es6" eklemeden es6 derlemesini hedeflemeyi seçmiş olabilirsiniz. Saygılarımızla
Freezystem

1
Merhaba @Freezystem, haklısın! Es2015'i hedefliyorum. Teşekkürler!
geri arama

@callback ES6 ve ES2015 aynı şey
DarkNeuron

66

ES6 ile kullanabilirsiniz Array.from(myNodeList). Ardından favori dizi yönteminizi kullanın.

var myNodeList = document.querySelectorAll('.my-selector');

// ALT 1
Array.from(myNodeList).forEach(function(el) {
  console.log(el);
});

Bunun eski tarayıcılarda da çalışmasını sağlamak için bir ES6 dolgusu kullanın .


Bir aktarıcı kullanıyorsanız (örneğin Babel) iki alternatif daha vardır:

var myNodeList = document.querySelectorAll('.my-selector');

// ALT 2
for (var el of myNodeList) {
  el.classList.add('active'); // or some other action
}

// ALT 3
[...myNodeList].forEach((el) => {
  console.log(el);
});

es6 altında bir nodeList'in bir yineleyici sağladığı da doğru değil mi?
cc young

4
@ccyoung, ancak yineleyici uyumlu olmayan ES6 tarayıcılarında çalışmaz çünkü Symbol nesnesini değiştiremezsiniz, bu nedenle kullanımı daha iyidir Array.from(myNodeList)çünkü parlatılabilir.
Roc

bu yüzden Array.from (el.childNodes) dizisinin bir parçası olarak ilk düğümü döndürmediği bir sorunum var.
zinoadidi

49

Prototipteki sliceyöntemi kullanarak onu bir diziye dönüştürebilirsiniz Array:

var elList = document.querySelectorAll('.viewcount');
elList = Array.prototype.slice.call(elList, 0);

Tüm ihtiyaç vardır Dahası, forEach, sen çağırabilir o gelen Arrayilk bir diziye onu zorlamak olmadan prototip:

var elList = document.querySelectorAll('.viewcount');
Array.prototype.forEach.call(elList, function(el) {
    console.log(el);
});

ES6'da, Array.fromonu bir diziye dönüştürmek için yeni işlevi kullanabilirsiniz :

Array.from(elList).forEach(function(el) {
    console.log(el);
});

Bu şu anda yalnızca yeni tarayıcılarda geçerlidir, ancak bir polyfill hizmeti kullanıyorsanız , bu işleve tümüyle erişebilirsiniz.


Bir ES6 aktarıcısı kullanıyorsanız , for..ofbunun yerine bir döngü bile kullanabilirsiniz :

for (var element of document.querySelectorAll('.some .elements')) {
  // use element here
}

Teşekkürler. daha yeni javascript düşünce / umut altında daha kısa ve öz bir zorlama olduğunu umuyordu.
cc young

6
@cc young - Bunun Array.prototype.forEachyerine kullanmamın [].forEachnedeni, ikincisinin tamamen gereksiz olan yeni bir Array nesnesi oluşturduğuna dikkat edin .
Joseph Silber

@JosephSilber ahh teşekkür ederim - oluşturulan yeni dizi boş []mu? Benim düşüncem çöplerin toplanacağı ve hafıza etkisinin ihmal edilebilir olduğu, herhangi biri bu konuda yorum yapabilir mi?
Daniel Sokolowski

@Daniel bu doğru, ama yine de diziyi yaratma ve yok etme hesaplamaları var.
Brett

21

Neden dönüştürmek? - callArray'in doğrudan öğe koleksiyonundaki işlevi;)

[].forEach.call( $('a'), function( v, i) {
    // do something
});

$ ' ın querySelectorAll için takma adınız olduğunu varsayarsak , tabii ki


düzenleme: ES6 daha da kısa sözdizimi sağlar [...$('a')]( Mayıs 2014 itibariyle, yalnızca Firefox işlerin )


Varsayalım $ki querySelectorAll.
c69

3
Cevabınız jQuery kullanımını ima ediyor. Eğer durum buysa, bu saçmalıklar sayesinde tamamen gereksizdir .each().
Matt Ball

1
hahaha neden ? hiçbir şey takma adlar yapmanızı yasaklamaz function $ ( s ) { return document.querySelectorAll(s); }.
c69

5
$('a').each(function(i, v) {...});
JQuery'yi

2
offtopic: EcmaScript 5 zaten bir yıldır bir standarttır, tüm mevcut nesil tarayıcılar yeni Arrays yöntemlerini destekler ve soru özellikle bu yöntemleri NodeList aka Element koleksiyonunda kullanmakla ilgiliydi.
c69

10

2020 güncellemesi: nodeList.forEach () artık resmi bir standarttır ve mevcut tüm tarayıcılarda desteklenmektedir.

Daha eski tarayıcılar aşağıdaki çoklu dolguyu kullanabilir.

Örneğin forEach () kullanarak javascript'teki listede çalışmak için, NodeList bir Array'e dönüştürülmelidir.

Bu doğru değil. .forEach()mevcut tarayıcılarda çalışır. Bu parametre eksik olursa, içinden .forEach () eklemek için bir polyfill kullanabilirsiniz Array için nodelist ve iyi çalışıyor:

if ( ! NodeList.prototype.forEach ) {
  NodeList.prototype.forEach = Array.prototype.forEach;
}

Şimdi çalıştırabilirsiniz:

myNodeList.forEach(function(node){...})

NodeLists'i Diziler gibi yinelemek için.

Bu, her yerde .call () 'dan çok daha kısa ve daha temiz bir kod üretir.


1
Bu cevap tam olarak ihtiyacım olan şeydi ve bu 3 satır çok zaman kazandırdı. Diğer tüm cevaplar bir grup kodu değiştirmeyi gerektirecekti ve nedenini anlamıyorum.
Scribblemacher

downvotes maymun yama yerleşik çünkü muhtemelen prototipler kötü uygulama olarak kabul edilir
DuBistKomisch

@DuBistKomisch Bu bir çoklu dolgudur, yalnızca standart NodeList.foreach () mevcut değilse uygulanır.
mikemaccana

2
ah benim hatam, gerçekten forEachözel olarak eklediklerini fark etmedim , buraya aramaya geldimfilter
DuBistKomisch

@DuBistKomisch için aynı tekniği kullanabilirsiniz filter, ancak NodeList.prototype.dbkFilterfarklı bir uygulama kullanarak gelecekteki bir standart için endişeleniyorsanız , ona resmi olmayan bir ad veya benzeri bir ad vermek isteyebilirsiniz .
mikemaccana

9

Olmak zorunda mı forEach? forListeyi yinelemek için basitçe bir döngü kullanabilirsiniz :

for (var i = 0; i < elementList.length; i++) {
    doSomethingWith(elementlist.item(i));
}

1
Gereksiz dizi dönüşümleri eklemeyen basit çözüme gitmek için +1. Bilginize, Bunun yerine elementList.item(i)sadece kullanabilirsiniz elementList[i].
jfriend00

4
şahsen forEach()daha iyi bir programlama stili buluyorum ve daha az ayrıntılı - ymmv
cc young

@cc young: Aslında sana katılıyorum. En sevdiğim kalıbı kullanabilmek için bir dönüştürme çalıştırmam gereken bu gibi durumlar dışında. Bu onu hantal yapar ve şöyle görünür: "Sahip olduğunuz tek şey bir çekiç olduğunda, her şey çivi gibi görünmeye başlar."
nfechner

Ve işte daha çılgın bir yol :) for (var oElement, i = 0; oElement = aMenuItemsElements; i++ { console.log(oElement); }
Daniel Sokolowski

Buradaki sorun, başka bir for (var i…)döngüyü iç içe geçirememenizdir çünkü for döngüsü kendi kapsamını oluşturmaz (şimdi C / C ++ 'da olduğu gibi). Ve sonra ikarışır.
Jens

2

ES6 gibi harika yollara izin verir var nodeArray = Array.from(nodeList)ama benim favorim yeni serpme operatörü.

var nodeArray = Array(...nodeList);

Mükemmel bir çözüm! Bu çözüm Typescript için de geçerlidir.
Nirus

ES5'e veya daha düşük bir sürüme aktarmadığınız sürece, bunun yalnızca TypeScript ile çalıştığını eklemek isterim.
Rudey

2

ES6'da benimle çalıştı

bunun gibi nodelistiniz olduğunu varsayalım

<ul>
  <li data-time="5:17">Flexbox video</li>
  <li data-time="8:22">Flexbox video</li>
  <li data-time="3:24">Redux video</li>
  <li data-time="5:17">Flexbox video</li>
  <li data-time="7:17">Flexbox video</li>
  <li data-time="4:17">Flexbox video</li>
  <li data-time="2:17">Redux video</li>
  <li data-time="7:17">Flexbox video</li>
  <li data-time="9:54">Flexbox video</li>
  <li data-time="5:53">Flexbox video</li>
  <li data-time="7:32">Flexbox video</li>
  <li data-time="2:47">Redux video</li>
  <li data-time="9:17">Flexbox video</li>

</ul>


const items = Array.from(document.querySelectorAll('[data-time]'));

console.log(items);

2

Aşağıdakileri kullanıyorum çünkü okumanın en kolay yolu olduğunu düşünüyorum:

const elements = document.getElementsByClassName('element');
[...elements].forEach((element) => {
   // code
});



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.