forEach, JavaScript dizisiyle ilgili bir işlev hatası değildir


145

Basit bir döngü yapmaya çalışıyorum:

const parent = this.el.parentElement
console.log(parent.children)
parent.children.forEach(child => {
  console.log(child)
})

Ancak aşağıdaki hatayı alıyorum:

VM384: 53 Yakalanmayan TypeError: parent.children.forEach bir işlev değil

parent.childrenGünlükler olmasına rağmen :

resim açıklamasını buraya girin

Sorun ne olabilir?

Not: İşte bir JSFiddle .


Aynı sorun element.siblings'de de görülür
Daut

@Daut evet çünkü element.siblings bir HTMLCollection döndürür ve HTMLCollections forEach () yöntemine sahip değildir
Freddo

1
hey sen, google araştırmacı! Bu çift okuyorsanız, foreach yerine her biri büyük E harfi ile olup olmadığını kontrol edin ....
Robert Sinclair

Yanıtlar:


127

İlk seçenek: dolaylı olarak her birini çağırın

parent.childrenNesne gibi bir dizi olduğunu. Aşağıdaki çözümü kullanın:

const parent = this.el.parentElement;

Array.prototype.forEach.call(parent.children, child => {
  console.log(child)
});

parent.childrenİsimli NodeListnesne çünkü böyle bir Array türü:

  • lengthDüğüm sayısını gösteren özelliği içerir
  • Her düğüm, 0'dan başlayarak sayısal ada sahip bir özellik değeridir: {0: NodeObject, 1: NodeObject, length: 2, ...}

Bu makalede daha fazla ayrıntı görün .


İkinci seçenek: yinelenebilir protokolü kullanın

parent.childrenbir HTMLCollection: yinelenebilir protokol uygular . ES2015 ortamında, HTMLCollectionyinelenebilirleri kabul eden herhangi bir yapıda kullanabilirsiniz.

HTMLCollectionForma operatörü ile kullanın :

const parent = this.el.parentElement;

[...parent.children].forEach(child => {
  console.log(child);
});

Veya for..ofdöngü ile (bu benim tercih ettiğim seçenek):

const parent = this.el.parentElement;

for (const child of parent.children) {
  console.log(child);
}

Çözümünüzü kullandığımda artık sorunum yok, ancak anonimleştirilmiş işlevin içindeki kod yürütülmüyor. .so ..
Jérémy

Hangi tarayıcıyı kullanacağınız, böylece parent.children size bir nodeList olduğunu söyler. Firefox'ta bana bir HTMLCection olduğunu söylüyor. Bir nodeList olsaydı, .forEach () işe yarar
Freddo

104

parent.childrenbir dizi değil. HTMLCollection ve forEachyöntemi yoktur. Önce diziye dönüştürebilirsiniz. Örneğin ES6'da:

Array.from(parent.children).forEach(child => {
    console.log(child)
});

veya forma operatörünü kullanarak:

[...parent.children].forEach(function (child) {
    console.log(child)
});

9
Bu çözümü Array prototipiyle uğraşmaktan daha çok tercih ediyorum.
Daut

Ve bu cevap OP sorularına doğru cevaplardan biridir. parent.children bir .forEach yöntemi olmayan bir HTMLCollection
Freddo

18

parent.childrendüğüm listesi listesi, teknik olarak bir html Koleksiyonu döndürür . Nesne gibi bir dizi, ancak bir dizi değil, bu nedenle dizi işlevlerini doğrudan çağıramazsınız. Bu bağlamda, bunu Array.from()gerçek bir diziye dönüştürmek için kullanabilirsiniz ,

Array.from(parent.children).forEach(child => {
  console.log(child)
})

Hayır, parent.children bir nodeList değil, bir HTML Koleksiyonu döndürür. Aynı şey değil. Eğer bir nodeList olsaydı, .forEach işe yarar
Freddo

12

Daha saf bir sürüm, en azından dönüşüm ve ES6 olmadan tüm cihazlarda çalışacağından eminsiniz:

const children = parent.children;
for (var i = 0; i < children.length; i++){
    console.log(children[i]);
}

https://jsfiddle.net/swb12kqn/5/


2
Tüm bu yeni ES6 işlevleri mevcut olanla aynı iyi eski şeyi yapıyor, ancak her zamanki gibi JS
Freddo

8

parent.childrena, HTMLCollectionnesne dizi benzeri olan. Öncelikle, bir gerçek dönüştürmek zorunda Arraykullanımı Array.prototypeyöntemlerle.

const parent = this.el.parentElement
console.log(parent.children)
[].slice.call(parent.children).forEach(child => {
  console.log(child)
})

2
Veya dönüştürmeyin, ancak .forEach () üzerinde .call () kullanın?
nnnnnn

@nnnnnn Cevabımı aşağıda görebilirsiniz.
Dmitri Pavlutin

Dizi benzeri nesneyi bir Array'a dönüştürmenin birçok yolu vardır :) Bu
Dmitriy

@DmitriyLoskutov Dönüştürmeniz gerekmez - JavaScript bir ördek yazma dilidir. Sadece bu özelliği kullanın.
Dmitri Pavlutin

5

Bunun nedeni parent.childrenbir NodeList olması ve .forEachyöntemi desteklememesidir (NodeList, yapı gibi bir dizi değil, bir dizi değil), bu yüzden önce onu kullanarak diziye dönüştürerek çağırmayı deneyin.

var children = [].slice.call(parent.children);
children.forEach(yourFunc);

Hayır, bir NodeList değil, bir HTML Koleksiyonu
Freddo

5

Gerek yokforEach , sadece from's ikinci parametresini kullanarak yineleyebilirsiniz , şöyle:

let nodeList = [{0: [{'a':1,'b':2},{'c':3}]},{1:[]}]
Array.from(nodeList, child => {
  console.log(child)
});


Üzücü haber şu ki parent.children bir nodeList değil ... .from () işe yaramaz.
Freddo

@Cedric, nesneniz bir NodeList değilse, özellikle adresleme için yeni bir soru sormalısınız. Burada, cevap özünde yanlış veya zararlı olduğunda aşağı oylama kullanılır ve kod snippet'inde görebileceğiniz gibi, nesnenin tüm öğeleri yinelenir ve yazdırılır, bu OP'nin sorusunun amacıdır.
Armfoot

Evet, sorun şu ki OP'nin bir nodeList ile değil, bir HTML Koleksiyonu ile ilgili sorusu ... Yani cevap basitçe soruyu cevaplamıyordu
Freddo

@Cedric Array.from, ilk parametrede verilen nesneyi bir diziye dönüştürdüğü için bu cevap bir HTML Koleksiyonu üzerinde de yinelenecektir . Sonuç, ekstra bir döngüye ( MDN belgeleri) gerek kalmadan madox2'nin cevabı ile aynıdır . forEachArray.from
Armfoot

4

Bunun NodeListgibi bir döngü üzerinde çalışıyorsanız :

const allParagraphs = document.querySelectorAll("p");

Bu şekilde döngü tavsiye ederim:

Array.prototype.forEach.call(allParagraphs , function(el) {
    // Write your code here
})

Şahsen, birkaç yol denedim ama çoğu bir döngü üzerinde çalışmak istediğim gibi çalışmadı NodeList, ama bu bir cazibe gibi çalışıyor, bir deneyin!

Bu NodeListbir Array değil, ancak bunu Array olarak ele alıyoruz, Array.Yani kullanarak , eski tarayıcılarda desteklenmediğini bilmeniz gerekir!

Hakkında daha fazla bilgiye NodeListmi ihtiyacınız var ? Lütfen MDN ile ilgili belgelerini okuyun .


1
Bu cevap açıkça nodeList üzerinde çalışıyor. Sorun parent.children bir nodeList olmayan bir HTML Koleksiyonu döndürür ...
Freddo

3

ES6'nın özelliklerini ( ok işlevleri ) kullandığınız için , aşağıdaki gibi bir for döngüsü de kullanabilirsiniz :

for(let child of [{0: [{'a':1,'b':2},{'c':3}]},{1:[]}]) {
  console.log(child)
}


Upvoted. Ne bir bükülme, ES6 sözdizimi, ama ... Ağlamak istememi sağlıyor ve C ++ geçmişinden geliyorum ...
Freddo

1

Yazdığınız olmadığını kontrol edebilirsiniz forEach doğru yazdığınız takdirde, foreach işe yaramaz diğer programlama dillerinde gibi.


0

Sen kullanabilirsiniz childNodesyerine children, childNodesaynı zamanda tarayıcı uyumluluk sorunları, fazla bilgi göz önüne alındığında daha güvenilir burada :

parent.childNodes.forEach(function (child) {
    console.log(child)
});

veya forma operatörünü kullanarak:

[...parent.children].forEach(function (child) {
    console.log(child)
});
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.