Javascript hoe bovenliggende elementen te verkrijgen. DOM-technieken: ouder-, kind- en buurelementen. Standaardacties voorkomen

De voorElke() methode voert een opgegeven functie één keer uit voor elk array-element.

De bron voor dit interactieve voorbeeld is opgeslagen in een GitHub-repository. Als u wilt bijdragen aan het interactieve voorbeeldenproject, kloon dan https://github.com/mdn/interactive-examples en stuur ons een pull-verzoek.

Syntaxis

arr .forEach(callback(currentValue [, index [, array]]) [, thisArg ])

Parameters

callback Functie die op elk element moet worden uitgevoerd. Het accepteert één tot drie argumenten: currentValue Het huidige element dat in de array wordt verwerkt.

index Optioneel De index currentValue in de array.

array Optioneel Er is een beroep gedaan op de array forEach().

thisArg Optionele waarde die als volgt moet worden gebruikt bij het uitvoeren van callback .

Retourwaarde

  1. Beschrijving
  2. forEach() roept een opgegeven callback-functie één keer aan voor elk element in een array, in oplopende volgorde. Er wordt geen beroep gedaan op indexeigenschappen die zijn verwijderd of niet zijn geïnitialiseerd. (Voor schaarse arrays, .)
  3. callback wordt aangeroepen met drie argumenten:

de waarde van het element

de index van het element

het Array-object dat wordt doorlopen

Als een parameter thisArg wordt opgegeven aan forEach() , zal deze worden gebruikt als callback van deze waarde. De thisArg-waarde is uiteindelijk waarneembaar door callback en wordt bepaald volgens de gebruikelijke regels voor het bepalen van de waarde die door een functie wordt gezien.

Er is geen andere manier om een ​​forEach()-lus te stoppen of te verbreken dan door een uitzondering te genereren. Als je dergelijk gedrag nodig hebt, is de methode forEach() het verkeerde hulpmiddel.

Voortijdige beëindiging kan worden bereikt met:

Arraymethoden: every() , some() , find() en findIndex() testen de array-elementen met een predikaat dat een waarheidsgetrouwe waarde retourneert om te bepalen of verdere iteratie vereist is.

Voorbeelden

Geen bewerking voor niet-geïnitialiseerde waarden (sparse arrays)

const arraySparse = let numCallbackRuns = 0 arraySparse.forEach(function(element)( console.log(element) numCallbackRuns++ )) console.log("numCallbackRuns: ", numCallbackRuns) // 1 // 3 // 7 // numCallbackRuns: 3 // commentaar: zoals je kunt zien, heeft de ontbrekende waarde tussen 3 en 7 geen callback-functie aangeroepen.

Een for-lus converteren naar forEach

const items = ["item1", "item2", "item3"] const copy = // before for (laat i = 0; i< items.length; i++) { copy.push(items[i]) } // after items.forEach(function(item){ copy.push(item) })

De inhoud van een array afdrukken

Opmerking: Om de inhoud van een array in de console weer te geven, kunt u console.table() gebruiken, waarmee een geformatteerde versie van de array wordt afgedrukt.

Het volgende voorbeeld illustreert een alternatieve aanpak, waarbij forEach() wordt gebruikt.

De volgende code registreert een regel voor elk element in een array:

Functie logArrayElements(element, index, array) ( console.log("a[" + index + "] = " + element) ) // Merk op dat index 2 wordt overgeslagen, omdat er geen item is op // die positie in de array... .forEach(logArrayElements) // logs: // a = 2 // a = 5 // a = 9

Met behulp van deze Arg

Het volgende (gekunstelde) voorbeeld werkt de eigenschappen van een object bij vanaf elke vermelding in de array:

Functie Counter() ( this.sum = 0 this.count = 0 ) Counter.prototype.add = function(array) ( array.forEach(function(entry) ( this.sum += entry ++this.count ), this ) // ^---- Opmerking ) const obj = new Counter() obj.add() obj.count // 3 obj.sum // 16

Omdat de parameter thisArg (this) wordt opgegeven aan forEach() , wordt deze elke keer dat deze wordt aangeroepen doorgegeven aan callback. De callback gebruikt deze als de this-waarde.

Een objectkopieerfunctie

Met de volgende code wordt een kopie van een bepaald object gemaakt.

Er zijn verschillende manieren om een ​​kopie van een object te maken. Het volgende is slechts één manier en wordt gepresenteerd om uit te leggen hoe Array.prototype.forEach() werkt met behulp van ECMAScript 5 Object.* meta-eigenschapsfuncties.

Functie kopiëren(obj) ( const copy = Object.create(Object.getPrototypeOf(obj)) const propNames = Object.getOwnPropertyNames(obj) propNames.forEach(function(naam) ( const desc = Object.getOwnPropertyDescriptor(obj, naam) Object .defineProperty(copy, name, desc) )) return copy ) const obj1 = ( a: 1, b: 2 ) const obj2 = copy(obj1) // obj2 ziet er nu uit als obj1

Als de array tijdens iteratie wordt gewijzigd, kunnen andere elementen worden overgeslagen.

In het volgende voorbeeld wordt "one" , "two" , "four" geregistreerd.

Wanneer de invoer met de waarde "two" is reached, the first entry of the whole array is shifted off-resulting in all remaining entries moving up one position. Because element "four" is now at an earlier position in the array, "three" will be skipped.!}

forEach() maakt geen kopie van de array vóór de iteratie.

Laat woorden = ["één", "twee", "drie", "vier"] woorden.forEach(function(woord) ( console.log(woord) if (woord === "twee") ( woorden.shift( ) ) )) // één // twee // vier

Maak een array plat

Het volgende voorbeeld is alleen bedoeld voor leerdoeleinden. Als je een array wilt afvlakken met behulp van ingebouwde methoden, kun je Array.prototype.flat() gebruiken (dat naar verwachting deel zal uitmaken van ES2019 en al in sommige browsers is geïmplementeerd).

/** * Maakt doorgegeven array in eendimensionale array plat * * @params (array) arr * @returns (array) */ function flatten(arr) ( const resultaat = arr.forEach((i) => ( if (Array. isArray(i)) ( result.push(...flatten(i)) ) else ( result.push(i) )) return resultaat ) // Gebruik const probleem = , 8, 9]] flatten(probleem) / /

Opmerking over het gebruik van Promises of asynchrone functies

laat beoordelingen = laat som = 0 laat somFunctie = asynchrone functie (a, b) ( retourneer a + b ) ratings.forEach(asynchrone functie(beoordeling) ( som = wacht op somFunctie(som, beoordeling) )) console.log(som) // Verwachte output: 14 // Werkelijke output: 0

Specificaties

Specificatie Status Opmerking
ECMAScript nieuwste concept (ECMA-262)
Voorlopige versie
ECMAScript 2015 (6e editie, ECMA-262)
De definitie van "Array.prototype.forEach" in die specificatie.
Standaard
ECMAScript 5.1 (ECMA-262)
De definitie van "Array.prototype.forEach" in die specificatie.
Standaard Initiële definitie. Geïmplementeerd in JavaScript 1.6.

Browsercompatibiliteit

De compatibiliteitstabel op deze pagina is gegenereerd op basis van gestructureerde gegevens. Als je wilt bijdragen aan de gegevens, ga dan naar https://github.com/mdn/browser-compat-data en stuur ons een pull-verzoek.

Update compatibiliteitsgegevens op GitHub

BureaubladMobielServer
ChroomRandFirefoxInternet ExplorerOperaSafariAndroid-webweergaveChroom voor AndroidFirefox voor AndroidOpera voor AndroidSafari op iOSSamsung-internetKnooppunt.js
voorElkChrome Volledige ondersteuning 1Rand Volledige ondersteuning 12Firefox Volledige ondersteuning 1.5IE Volledige ondersteuning 9Opera Volledige ondersteuning JaSafari Volledige ondersteuning 3WebView Android Volledige ondersteuning ≤37Chrome Android Volledige ondersteuning 18Firefox Android Volledige ondersteuning 4Opera Android Volledige ondersteuning JaSafari iOS Volledige ondersteuning 1Samsung Internet Android Volledige ondersteuning 1.0nodejs Volledige ondersteuning Ja
  • I. Itereren over echte arrays
    1. voorElke methode en gerelateerde methoden
    2. voor lus
    3. Correct gebruik van de for...in-lus
    4. for...of loop (impliciet gebruik van iterator)
    5. Expliciet gebruik van iterator
  • II. Itereren over array-achtige objecten
    1. Methoden gebruiken om echte arrays te herhalen
    2. Converteren naar een echte array
    3. Een opmerking over runtime-objecten

I. Itereren over echte arrays

Op dit moment zijn er drie manieren om de elementen van een echte array te herhalen:

  1. methode Array.prototype.forEach ;
  2. klassiek voor lus
  3. een “correct” geconstrueerde for...in-lus.

Bovendien worden er binnenkort, met de komst van de nieuwe ECMAScript 6 (ES 6)-standaard, nog twee methoden verwacht:

  1. for...of loop (impliciet gebruik van iterator);
  2. expliciet gebruik van iterator.

1. De forEach-methode en gerelateerde methoden

Als uw project is ontworpen om de functies van de ECMAScript 5 (ES5)-standaard te ondersteunen, kunt u een van de innovaties ervan gebruiken: de forEach-methode.

Gebruiksvoorbeeld:

Vara = ["a", "b", "c"]; a.forEach(function(entry) ( console.log(entry); ));

Over het algemeen vereist het gebruik van forEach verbinding met de es5-shim-emulatiebibliotheek voor browsers die deze methode niet standaard ondersteunen. Deze omvatten IE 8 en eerder, die op sommige plaatsen nog steeds in gebruik zijn.

Het voordeel van forEach is dat het niet nodig is om lokale variabelen te declareren om de index en waarde van het huidige array-element op te slaan, omdat deze automatisch als argumenten aan de callback-functie worden doorgegeven.

Als u zich zorgen maakt over de mogelijke kosten van het terugbellen op elk element, hoeft u zich geen zorgen te maken en dit te lezen.

forEach is ontworpen om door alle elementen van een array te itereren, maar daarnaast biedt ES5 nog een aantal handige methoden om door alle of sommige elementen te itereren, plus het uitvoeren van enkele acties erop:

  • every-retourneert true als de callback voor elk element van de array een waarde retourneert die naar true kan worden geconverteerd.
  • some - retourneert waar als voor ten minste één element van de array de callback een waarde retourneert die naar waar kan worden geconverteerd.
  • filter: creëert een nieuwe array die de elementen van de originele array bevat waarvoor de callback true retourneert.
  • map - creëert een nieuwe array bestaande uit de waarden die worden geretourneerd door de callback.
  • reduce - reduceert een array tot één enkele waarde, waarbij op zijn beurt een callback wordt toegepast op elk array-element, te beginnen met het eerste (kan handig zijn voor het berekenen van de som van array-elementen en andere samenvattingsfuncties).
  • reduceRight - werkt op dezelfde manier als reduceren, maar doorloopt de elementen in omgekeerde volgorde.

2. Voor lus

Goed oud voor regels:

Var a = ["a", "b", "c"]; var-index; voor (index = 0; index< a.length; ++index) { console.log(a); }

Als de lengte van de array constant is gedurende de hele lus, en de lus zelf tot een prestatiekritisch codegedeelte behoort (wat onwaarschijnlijk is), dan kun je een “meer optimale” versie van gebruiken, waarin de lengte van de array wordt opgeslagen. :

Vara = ["a", "b", "c"]; var-index, len; voor (index = 0, len = a.lengte; index< len; ++index) { console.log(a); }

In theorie zou deze code iets sneller moeten werken dan de vorige.

Als de volgorde van de elementen niet belangrijk is, kun je nog verder gaan in termen van optimalisatie en de variabele verwijderen voor het opslaan van de lengte van de array, door de volgorde van de zoekopdracht in omgekeerde volgorde te veranderen:

Var a = ["a", "b", "c"]; var-index; for (index = a.length - 1; index >= 0; --index) ( console.log(a); )

In moderne JavaScript-engines betekenen dergelijke optimalisatiespellen echter meestal niets.

3. Correct gebruik van de for...in-lus

Als u wordt geadviseerd een for...in-lus te gebruiken, onthoud dan dat itereren over arrays niet is bedoeld. In tegenstelling tot wat vaak wordt gedacht, itereert de for...in-lus niet via array-indices, maar eerder via opsombare eigenschappen van een object.

In sommige gevallen kan for...in echter nuttig zijn, bijvoorbeeld bij het herhalen van verspreide arrays, zolang u voorzorgsmaatregelen neemt, zoals weergegeven in het onderstaande voorbeeld:

// a - schaarse array var a = ; een = "een"; een = "b"; een = "c"; for (var sleutel in a) ( if (a.hasOwnProperty(sleutel) && /^0$|^d*$/.test(sleutel) && sleutel<= 4294967294) { console.log(a); } }

In dit voorbeeld worden bij elke iteratie van de lus twee controles uitgevoerd:

  1. dat de array zijn eigen eigenschap heeft, genaamd key (niet geërfd van het prototype).
  2. die sleutel is een tekenreeks die de decimale representatie bevat van een geheel getal waarvan de waarde kleiner is dan 4294967294 . Waar komt het laatste getal vandaan? Uit de definitie van een array-index in ES5, waaruit blijkt dat de hoogste index die een element in een array kan hebben, is: (2^32 - 2) = 4294967294 .

Dergelijke controles zullen uiteraard onnodige tijd in beslag nemen bij het uitvoeren van de lus. Maar in het geval van een schaarse array is deze methode efficiënter dan een for-lus, omdat in dit geval alleen de elementen worden herhaald die expliciet in de array zijn gedefinieerd. In het bovenstaande voorbeeld worden dus slechts 3 iteraties uitgevoerd (voor de indexen 0, 10 en 10000) - versus 10001 in de for-lus.

Om niet elke keer zo'n omslachtige controlecode te schrijven als je door een array moet itereren, kun je deze als een aparte functie schrijven:

Functie arrayHasOwnIndex(array, sleutel) ( return array.hasOwnProperty(sleutel) && /^0$|^d*$/.test(sleutel) && sleutel<= 4294967294; }

Dan wordt het lichaam van de lus uit het voorbeeld aanzienlijk verkleind:

For (toets a in) ( if (arrayHasOwnIndex(a, key)) ( console.log(a); ) )

De hierboven besproken controlecode is universeel en geschikt voor alle gevallen. Maar in plaats daarvan kunt u een kortere versie gebruiken, hoewel formeel niet helemaal correct, maar toch geschikt voor de meeste gevallen:

For (toets a in) ( if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === sleutel) ( console.log(a); ) )

4. For...of loop (impliciet gebruik van iterator)

ES6, dat zich nog steeds in de conceptstatus bevindt, zou iterators in JavaScript moeten introduceren.

Iterator is een protocol geïmplementeerd door een object dat een standaardmanier definieert om een ​​reeks waarden te verkrijgen (eindig of oneindig).
Een object heeft een iterator als het een next()-methode definieert, een functie zonder argumenten die een object retourneert met twee eigenschappen:

  1. done (boolean) - waar als de iterator het einde van de itereerbare reeks heeft bereikt. Anders is de waarde false .
  2. waarde - definieert de waarde die door de iterator wordt geretourneerd. Kan ongedefinieerd zijn (ontbreekt) als de eigenschap done waar is.

Veel inbouwobjecten, incl. echte arrays hebben standaard iteratoren. De eenvoudigste manier om een ​​iterator op echte arrays te gebruiken, is door de nieuwe for...of-constructie te gebruiken.

Voorbeeld van gebruik voor...van:

Varval; var a = ["a", "b", "c"]; voor (val van a) ( console.log(val); )

In het bovenstaande voorbeeld roept de for...of-lus impliciet de iterator van het Array-object aan om elke waarde van de array te verkrijgen.

5. Expliciet gebruik van iterator

Iterators kunnen ook expliciet worden gebruikt, maar in dit geval wordt de code veel complexer vergeleken met de for...of-lus. Het ziet er ongeveer zo uit:

Vara = ["a", "b", "c"]; var-invoer; while (!(entry = a.next()).done) ( console.log(entry.value); )

II. Itereren over array-achtige objecten

Naast echte arrays zijn er in JavaScript ook array-achtige objecten . Wat ze gemeen hebben met echte arrays is dat ze een lengte-eigenschap hebben en eigenschappen die worden genoemd als getallen die overeenkomen met de elementen van de array. Voorbeelden hiervan zijn de DOM van de NodeList-verzameling en de argumenten pseudo-array, beschikbaar binnen elke functie/methode.

1. Methoden gebruiken om echte arrays te herhalen

Op zijn minst kunnen de meeste, zo niet alle, methoden voor het itereren over echte arrays worden gebruikt om array-achtige objecten te itereren.

De for en for...in-constructies kunnen op precies dezelfde manier worden toegepast op array-achtige objecten als op echte arrays.

forEach en andere Array.prototype-methoden zijn ook van toepassing op array-achtige objecten. Om dit te doen, moet u Function.call of Function.apply gebruiken.

Als u bijvoorbeeld forEach wilt toepassen op de eigenschap childNodes van een Node-object, doet u dat als volgt:

Array.prototype.forEach.call(node.childNodes, function(child) (//doe iets met het onderliggende object));

Om deze truc gemakkelijker te kunnen hergebruiken, kun je een verwijzing naar de methode Array.prototype.forEach in een afzonderlijke variabele declareren en deze als snelkoppeling gebruiken:

// (Ervan uitgaande dat alle onderstaande code binnen hetzelfde bereik valt) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // doe iets met het onderliggende object));

Als een array-achtig object een iterator heeft, kan deze expliciet of impliciet worden gebruikt om over het object te itereren op dezelfde manier als voor echte arrays.

2. Converteer naar een echte array

Er is ook een andere, heel eenvoudige manier om een ​​array-achtig object te herhalen: converteer het naar een echte array en gebruik een van de hierboven besproken methoden voor iteratie over echte arrays. Voor conversie kunt u de generieke methode Array.prototype.slice gebruiken, die op elk arrayachtig object kan worden toegepast. Dit gebeurt heel eenvoudig, zoals weergegeven in het onderstaande voorbeeld:

Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);

Als u bijvoorbeeld een NodeList-verzameling naar een daadwerkelijke array wilt converteren, heeft u zoiets als deze code nodig:

Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);

3. Een opmerking over runtime-objecten

Als u Array.prototype-methoden toepast op runtime-objecten (zoals DOM-collecties), moet u zich ervan bewust zijn dat deze methoden niet gegarandeerd correct werken in alle runtime-omgevingen (inclusief browsers). Dit hangt af van het gedrag van een bepaald object in een bepaalde uitvoeringsomgeving, of preciezer gezegd, van hoe de abstracte operatie HasProperty in dit object is geïmplementeerd. Het probleem is dat de ES5-standaard zelf rekening houdt met de mogelijkheid dat een object zich misdraagt ​​met betrekking tot deze bewerking (zie §8.6.2).

Daarom is het belangrijk om de werking van de Array.prototype-methoden te testen in elke runtime-omgeving (browser) waarin u uw applicatie wilt gebruiken.