kzen.dev
  • Frågor
  • Taggar
  • Användare
Meddelanden
Belöningar
Registrering
När du har registrerat dig kommer du att få information om svar och kommentarer på dina frågor.
Logga in
Om du redan har ett konto loggar du in för att kontrollera nya meddelanden.
Det kommer att finnas belöningar för frågor, svar och kommentarer.
Mer
Källa
Redigera
 Dante1986
Dante1986
Question

For-each över en array i JavaScript?

Hur kan jag gå igenom alla poster i en array med JavaScript?

Jag trodde att det var något liknande:

forEach(instance in theArray)

Där theArray är min array, men det verkar inte stämma.

4427 2012-02-17T13:51:48+00:00 3
T.J. Crowder
T.J. Crowder
Redigerad fråga 2019ör april 2019 в 2:14
Programmering
arrays
javascript
iteration
loops
foreach
Popular videos
Learn Javascript Programming #4: For Loops (Looping Through Numbers, Arrays, Objects)
Learn Javascript Programming #4: For Loops (Looping Through Numbers, Arrays, Objects)
för 6 år sedan
Урок 12. JavaScript. Методы массивов (forEach, map, filter, reduce, find, findIndex). Js Массивы.
Урок 12. JavaScript. Методы массивов (forEach, map, filter, reduce, find, findIndex). Js Массивы.
för 4 år sedan
forEach Array Method | JavaScript Tutorial
forEach Array Method | JavaScript Tutorial
för 3 år sedan
Using JavaScript forEach to Loop over an Array
Using JavaScript forEach to Loop over an Array
för 5 år sedan
Методы массивов: map, reduce, filter, forEach | JavaScript Array Methods
Методы массивов: map, reduce, filter, forEach | JavaScript Array Methods
för 2 år sedan
ForEach() Explained - A 5 minute Method-Masterclass
ForEach() Explained - A 5 minute Method-Masterclass
för 3 år sedan
ForEach Loop in JavaScript in Hindi 2020
ForEach Loop in JavaScript in Hindi 2020
för 3 år sedan
JavaScript Array forEach Method
JavaScript Array forEach Method
för 7 år sedan
JavaScript for Developers 44 - Array for each Method
JavaScript for Developers 44 - Array for each Method
för 7 år sedan
JavaScript Programming Tutorial 44 - forEach Method Arrays
JavaScript Programming Tutorial 44 - forEach Method Arrays
för 4 år sedan
8 Must Know JavaScript Array Methods
8 Must Know JavaScript Array Methods
för 4 år sedan
Foreach over an array in JavaScript?
Foreach over an array in JavaScript?
för 5 år sedan
Array forEach Method in JavaScript
Array forEach Method in JavaScript
för 2 år sedan
JavaScript Programming Tutorial 45 - Iterate Multidimensional Array with for and forEach
JavaScript Programming Tutorial 45 - Iterate Multidimensional Array with for and forEach
för 4 år sedan
Array Iteration: 8 Methods - map, filter, reduce, some, every, find, findIndex, forEach
Array Iteration: 8 Methods - map, filter, reduce, some, every, find, findIndex, forEach
för 6 år sedan
every Array Method | JavaScript Tutorial
every Array Method | JavaScript Tutorial
för 3 år sedan
JavaScript Higher Order Functions & Arrays
JavaScript Higher Order Functions & Arrays
för 5 år sedan
JavaScript array.forEach() 🔁
JavaScript array.forEach() 🔁
för 2 år sedan
Looping through an array of objects
Looping through an array of objects
för 7 år sedan
Objects: Nested Arrays & Objects--The Modern JavaScript Bootcamp
Objects: Nested Arrays & Objects--The Modern JavaScript Bootcamp
för 3 år sedan
JavaScript | S03E24 | Objects and Arrays, forEach
JavaScript | S03E24 | Objects and Arrays, forEach
för 5 år sedan
map vs filter vs forEach | JAVASCRIPT ARRAY METHODS | Codehood شرح بالعربى
map vs filter vs forEach | JAVASCRIPT ARRAY METHODS | Codehood شرح بالعربى
för 3 år sedan
Foreach array loop method in Javascript tutorial
Foreach array loop method in Javascript tutorial
för 3 år sedan
#2: Array .forEach() Method | JavaScript Array Methods
#2: Array .forEach() Method | JavaScript Array Methods
för 2 år sedan
CS-290: Array.forEach() Explanation
CS-290: Array.forEach() Explanation
för 2 år sedan
« Föregående
Nästa »
Den här frågan har 1 svar på engelska, för att läsa dem logga in på ditt konto.
Solution / Answer
T.J. Crowder
T.J. Crowder
2012ör februari 2012 в 1:53
2012-02-17T13:53:44+00:00
Mer
Källa
Redigera
#15459598

TL;DR

  • Använd inte for-in om du inte använder det med skyddsåtgärder eller om du åtminstone är medveten om varför det kan bita dig.
  • Dina bästa insatser är vanligtvis
  • en for-of-slinga (endast ES2015+),
  • Array#forEach (spec | MDN) (eller dess släktingar some och liknande) (endast ES5+),
  • en enkel gammaldags for-slinga,
  • eller for-in med skyddsåtgärder. Men det finns mycket mer att utforska, läs vidare...

    JavaScript har en kraftfull semantik för slinga genom arrayer och array-liknande objekt. Jag har delat upp svaret i två delar: Alternativ för äkta matriser och alternativ för saker som bara är array-liknande, som arguments-objektet, andra iterable-objekt (ES2015+), DOM-samlingar och så vidare. Jag ska snabbt notera att du kan använda ES2015-alternativen nu, även på ES5-motorer, genom att transportera ES2015 till ES5. Sök efter "ES2015 transpiling" / "ES6 transpiling" för mer... Okej, låt oss titta på våra alternativ:

    För faktiska matriser

    Du har tre alternativ i ECMAScript 5 ("ES5"), den version som har mest stöd för tillfället, och ytterligare två som lades till i ECMAScript 2015 ("ES2015", "ES6"):

  1. Använd forEach och relaterade (ES5+)
  2. Använd en enkel for-slinga.
  3. Använd for-in korrekt.
  4. Använd for-of (använd implicit en iterator) (ES2015+)
  5. Använd en iterator explicit (ES2015+) Detaljer:

    1. Använd forEach och relaterade

    I alla vagt moderna miljöer (alltså inte IE8) där du har tillgång till Array-funktionerna som lades till i ES5 (direkt eller med hjälp av polyfills) kan du använda forEach (spec | MDN):

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

forEach accepterar en callback-funktion och, som alternativ, ett värde som ska användas som this när callback-funktionen anropas (används inte ovan). Callback-funktionen anropas för varje post i matrisen, i turordning, och hoppar över icke-existerande poster i glesa matriser. Även om jag bara använde ett argument ovan, anropas callbacken med tre argument: Värdet för varje post, indexet för den posten och en referens till matrisen som du itererar över (om din funktion inte redan har den i handen). Om du inte stöder föråldrade webbläsare som IE8 (som NetApps visar har en marknadsandel på drygt 4 % när detta skrivs i september 2016) kan du utan problem använda forEach i en allmän webbsida utan shim. Om du behöver stödja föråldrade webbläsare är det lätt att shimma/polyfylla forEach (sök efter "es5 shim" för flera alternativ). forEach har den fördelen att du inte behöver deklarera indexerings- och värdevariabler i det innehållande scope, eftersom de levereras som argument till iterationsfunktionen och därmed är väl avgränsade till just den iterationen. Om du är orolig för körtidskostnaden för att göra ett funktionsanrop för varje arraypost behöver du inte vara det; details. Dessutom är forEach funktionen "loop through them all" men ES5 definierade flera andra användbara "work your way through the array and do things" funktioner, inklusive:

  • every (slutar att slinga första gången som callbacken returnerar false eller något annat felaktigt).
  • some (stoppar looping första gången callbacken returnerar true eller något sanningsenligt)
  • filter (skapar en ny array med element där filterfunktionen returnerar true och utelämnar de element där den returnerar false).
  • map (skapar en ny array av de värden som återges av callback-funktionen).
  • reduce (bygger upp ett värde genom att upprepade gånger anropa callbacken och skicka in tidigare värden; se specifikationen för detaljer; användbart för att summera innehållet i en array och många andra saker)
  • reduceRight (som reduce, men arbetar i fallande snarare än stigande ordning)

    2. Använd en enkel for-slinga

    Ibland är de gamla sätten bäst:

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

Om längden på arrayen inte ändras under slingan och det är i prestandakänslig kod (osannolikt) kan en något mer komplicerad version som tar fram längden i förväg vara en tiny bit snabbare:

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

Och/eller att räkna baklänges:

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

Men med moderna JavaScript-motorer är det sällan du behöver ta ut den sista biten juice. I ES2015 och senare kan du göra dina index- och värdevariabler lokala för for-slingan:

let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
    console.log(index, value);
}
//console.log(index);   // would cause "ReferenceError: index is not defined"
//console.log(value);   // would cause "ReferenceError: value is not defined"
let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
    console.log(index, value);
}
try {
    console.log(index);
} catch (e) {
    console.error(e);   // "ReferenceError: index is not defined"
}
try {
    console.log(value);
} catch (e) {
    console.error(e);   // "ReferenceError: value is not defined"
}

Och när du gör det skapas inte bara value utan även index för varje loop-iteration, vilket innebär att closures som skapas i loop-kroppen behåller en referens till index (och value) som skapats för den specifika iterationen:

let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        console.log("Index is: " + index);
    });
}
let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        console.log("Index is: " + index);
    });
}
<div>zero</div>
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>

Om du hade fem divs skulle du få "Index är: 0" om du klickar på den första och "Index är: 4" om du klickar på den sista. Detta fungerar inte om du använder var istället för let.

3. Använd for-in korrekt.

Du'får folk som säger att du ska använda for-in, men det'är inte vad for-in är till för. for-in loopar genom de uppräkneliga egenskaperna hos ett objekt, inte indexen i en array. Ordningsföljden är inte garanterad, inte ens i ES2015 (ES6). ES2015+ definierar en ordning för objektets egenskaper (via [[OwnPropertyKeys]], [[Enumerate]], och saker som använder dem som Object.getOwnPropertyKeys), men det definierar inte att for-in ska följa den ordningen. (Detaljer i detta andra svar.) De enda verkliga användningsområdena för for-in på en array är:

  • Det är en sparse arrays med massiva luckor i den, eller
  • Du använder egenskaper som inte är element och du vill inkludera dem i slingan. Om man bara tittar på det första exemplet: Du kan använda for-in för att besöka dessa sparese array-element om du använder lämpliga skyddsåtgärder:
// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
    if (a.hasOwnProperty(key)  &&        // These checks are
        /^0$|^[1-9]\d*$/.test(key) &&    // explained
        key <= 4294967294                // below
        ) {
        console.log(a[key]);
    }
}

Observera de tre kontrollerna:

  1. Att objektet har sin egna egenskap med det namnet (inte en som det ärver från sin prototyp), och
  2. Att nyckeln består av alla decimalsiffror (t.ex. normal strängform, inte vetenskaplig notation), och
  3. Att nyckelns värde när den omvandlas till ett tal är <= 2^32 - 2 (vilket är 4 294 967 294). Varifrån kommer det talet? Det är en del av definitionen av ett arrayindex [i specifikationen] (https://tc39.github.io/ecma262/#array-index). Andra tal (icke heltal, negativa tal, tal som är större än 2^32 - 2) är inte arrayindex. Anledningen till att det är 2^32 - 2 är att det gör det största indexvärdet ett lägre än 2^32 - 1, vilket är det maximala värdet som en array kan ha. (En array's längd ryms t.ex. i ett 32-bitars heltal utan förtecken.) (RobG fick beröm för att han i en kommentar till mitt blogginlägg påpekade att mitt tidigare test inte var helt rätt.) Du skulle naturligtvis inte göra det i inline-kod. Man skulle skriva en funktion. Kanske:
// Utility function for antiquated environments without `forEach`
var hasOwn = Object.prototype.hasOwnProperty;
var rexNum = /^0$|^[1-9]\d*$/;
function sparseEach(array, callback, thisArg) {
    var index;
    for (var key in array) {
        index = +key;
        if (hasOwn.call(a, key) &&
            rexNum.test(key) &&
            index <= 4294967294
            ) {
            callback.call(thisArg, array[key], index, array);
        }
    }
}

var a = [];
a[5] = "five";
a[10] = "ten";
a[100000] = "one hundred thousand";
a.b = "bee";

sparseEach(a, function(value, index) {
    console.log("Value at " + index + " is " + value);
});

4. Använd for-of (använd implicit en iterator) (ES2015+)

ES2015 lägger till iteratorer i JavaScript. Det enklaste sättet att använda iteratorer är det nya for-of-kommandot. Det ser ut så här: Det ser ut så här:

const a = ["a", "b", "c"];
for (const val of a) {
    console.log(val);
}

Under täckmanteln hämtar detta en iterator från arrayen och loopar genom den och hämtar värdena från den. Detta har inte samma problem som att använda for-in, eftersom det använder en iterator som definieras av objektet (matrisen), och matriser definierar att deras iteratorer itererar genom deras entries (inte deras egenskaper). Till skillnad från for-in i ES5 är den ordning i vilken posterna besöks den numeriska ordningen för deras index.

5. Använd en iterator explicit (ES2015+)

Ibland kanske du vill använda en iterator explicit. Det kan du också göra, även om det är mycket krångligare än for-of. Det ser ut så här:

const a = ["a", "b", "c"];
const it = a.values();
let entry;
while (!(entry = it.next()).done) {
    console.log(entry.value);
}

Iteratorn är ett objekt som motsvarar Iteratordefinitionen i specifikationen. Dess next-metod returnerar ett nytt resultatobjekt varje gång du anropar den. Resultatobjektet har en egenskap, done, som talar om huruvida den är klar, och en egenskap value med värdet för den iterationen. (done är valfritt om det skulle vara false, value är valfritt om det skulle vara undefined.) Betydelsen av value varierar beroende på iteratorn; matriser stöder (minst) tre funktioner som returnerar iteratorer:

  • values(): Detta är den som jag använde ovan. Den returnerar en iterator där varje värde är arrayposten för den iterationen ("a", "b" och "c" i exemplet tidigare).
  • keys(): Återger en iterator där varje "värde" är nyckeln för den iterationen (så för vår "a" ovan skulle det vara "0", sedan "1" och sedan "2").
  • entries(): Återger en iterator där varje värde är en array i formen [nyckel, värde] för den iterationen.

    För Array-liknande objekt

    Förutom äkta matriser finns det också matrisliknande objekt som har en egenskap length och egenskaper med numeriska namn: NodeList-instanser, arguments-objektet osv. Hur loopar vi genom deras innehåll?

    Använd något av alternativen ovan för matriser.

    Åtminstone några, och möjligen de flesta eller till och med alla, av ovanstående metoder för matriser gäller ofta lika bra för matrisliknande objekt:

  1. Använd forEach och relaterade (ES5+) De olika funktionerna i Array.prototype är "avsiktligt generiska" och kan vanligtvis användas på array-liknande objekt via Function#call eller Function#apply. (Se Caveat för host-provided objects i slutet av det här svaret, men det är ett sällsynt problem.) Anta att du vill använda forEach på en Node's childNodes-egenskap. Du skulle göra så här: Array.prototype.forEach.call(node.childNodes, function(child) { // Gör något med child. }); Om du kommer att göra detta ofta kanske du vill ta en kopia av funktionsreferensen till en variabel för återanvändning, t.ex: // (Allt detta är förmodligen i någon scoping-funktion). var forEach = Array.prototype.forEach; // Senare... forEach.call(node.childNodes, function(child) { // Gör något med child. });

  2. Använd en enkel for-slinga. En enkel for-slinga gäller naturligtvis för array-liknande objekt.

  3. Använd for-in korrekt. for-in med samma skyddsåtgärder som för en array bör fungera med array-liknande objekt också; förbehållet för host-provided objects på #1 ovan kan gälla.

  4. Använd for-of (använd implicit en iterator) (ES2015+) for-of kommer att använda den iterator som tillhandahålls av objektet (om det finns någon); vi måste se hur detta fungerar med de olika array-liknande objekten, särskilt de som tillhandahålls av värden. Specifikationen för NodeList från querySelectorAll har till exempel uppdaterats för att stödja iteration. Specifikationen för HTMLCollection från getElementsByTagName har inte ändrats.

  5. Använd en iterator explicit (ES2015+) Se #4, vi'måste se hur iteratorer fungerar.

    Skapa en sann array

    Andra gånger kanske du vill konvertera ett array-liknande objekt till en sann array. Att göra det är förvånansvärt enkelt:

  6. Använd slice metoden för arrays. Vi kan använda slice-metoden för arrays, som liksom de andra metoderna som nämns ovan är "avsiktligt generisk" och därför kan användas med array-liknande objekt, som här: Det kan till exempel användas så här: var trueArray = Array.prototype.slice.call(arrayLikeObject); Om vi till exempel vill konvertera en NodeList till en true array kan vi göra så här: Var divs = Array.prototype.slice.call(document.querySelectorAll("div")); Se Caveat för host-provided objects nedan. Observera särskilt att detta kommer att misslyckas i IE8 och tidigare, som inte låter dig använda host-provided objects som this på detta sätt.

  7. Använd spread syntax (...) Det är också möjligt att använda ES2015's spread syntax med JavaScript-motorer som stöder den här funktionen: var trueArray = [...iterableObject]; Om vi till exempel vill konvertera en NodeList till en true array blir det ganska kortfattat med spread syntax: Var divs = [...document.querySelectorAll("div")];

  8. Använd Array.from (spec) | (MDN) Array.from (ES2015+, men lätt att fylla ut) skapar en array från ett arrayliknande objekt, och skickar eventuellt posterna genom en mappningsfunktion först. Så: var divs = Array.from(document.querySelectorAll("div")); Om du vill få fram en matris med taggnamnen för element med en viss klass använder du mappningsfunktionen: // Arrow-funktion (ES2015): Var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName); // Standardfunktion (eftersom Array.from kan vara shimmed): var divs = Array.from(document.querySelectorAll(".some-class"), function(element) { return element.tagName; });

    Caveat för objekt som tillhandahålls av värden

    Om du använder Array.prototype-funktioner med host-provided array-liknande objekt (DOM-listor och andra saker som tillhandahålls av webbläsaren snarare än JavaScript-motorn) måste du vara säker på att testa i dina målmiljöer för att se till att det host-provided objektet beter sig korrekt. De flesta beter sig korrekt (nu), men det är viktigt att testa. Anledningen är att de flesta metoderna i Array.prototype som du sannolikt kommer att vilja använda är beroende av att det objekt som tillhandahålls av värden ger ett ärligt svar på den abstrakta operationen [[HasProperty]]. I skrivande stund gör webbläsare ett mycket bra jobb med detta, men 5.1-specifikationen tillåter möjligheten att ett objekt som tillhandahålls av värden kanske inte är ärligt. Det står i §8.6.2, flera stycken under den stora tabellen i början av avsnittet, där det står: En möjlighet är till exempel att [[Get]] och [[Put]] för ett visst värdobjekt verkligen hämtar och lagrar egenskapsvärden men att [[HasProperty]] alltid genererar false. (Jag kunde inte hitta motsvarande formulering i ES2015-specifikationen, men det är säkert fortfarande fallet.) Igen, i skrivande stund hanterar de vanliga array-liknande objekten i moderna webbläsare [t.ex. NodeList-instanser] de facto [[HasProperty]]` korrekt, men det är viktigt att testa).

T.J. Crowder
T.J. Crowder
Redigerat svar 2019ör mars 2019 в 11:19
6745
0
Do you have a question? Add it on the site and get an answer instantly
en.kzen.dev
 PatrikAkerstrand
PatrikAkerstrand
2012ör februari 2012 в 1:55
2012-02-17T13:55:11+00:00
Mer
Källa
Redigera
#15459599

Note: Detta svar är hopplöst föråldrat. För ett mer modernt tillvägagångssätt, se de metoder som finns tillgängliga för en array. Metoder av intresse kan vara:

  • forEach
  • Map
  • filter
  • zip
  • minska
  • varje
  • några

Standardmetoden för att iterera en array i JavaScript är en vanlig for-slinga:

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element
}

Observera dock att detta tillvägagångssätt endast är bra om du har en tät array och varje index är upptaget av ett element. Om arrayen är gles kan du få prestandaproblem med detta tillvägagångssätt, eftersom du kommer att iterera över en massa index som inte verkligen finns i arrayen. I det här fallet kan en for .. in-slinga vara en bättre idé. **Du måste dock använda lämpliga skyddsåtgärder för att se till att endast de önskade egenskaperna hos matrisen (dvs. matrisens element) behandlas, eftersom for..in-slingan också kommer att räknas upp i äldre webbläsare, eller om de ytterligare egenskaperna är definierade som enumerable.

I ECMAScript 5 kommer det att finnas en forEach-metod på arrayprototypen, men den stöds inte i äldre webbläsare. Så för att kunna använda den konsekvent måste du antingen ha en miljö som stöder den (till exempel Node.js för JavaScript på serversidan) eller använda en "Polyfill". Polyfill för denna funktionalitet är dock trivial och eftersom den gör koden lättare att läsa är det en bra polyfill att inkludera.

Peter Mortensen
Peter Mortensen
Redigerat svar 2019ör september 2019 в 7:57
489
0
Do you have a question? Add it on the site and get an answer instantly
en.kzen.dev
 Quentin
Quentin
2012ör februari 2012 в 1:55
2012-02-17T13:55:46+00:00
Mer
Källa
Redigera
#15459600

Om du vill gå i en loop över en array använder du den vanliga tredelade for-slingan.

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

Du kan optimera prestandan genom att cachelagra myArray.length eller genom att iterera över den baklänges.

39
0
Lägg till en fråga
Kategorier
Alla
Teknik
Kultur / fritid
Livet / Konst
Vetenskap
Professionell
Företag
Användare
Alla
Ny
Populära
1
Andrei Kalinin
Registrerad för 2 veckor sedan
2
Koroleva Ego
Registrerad för 1 månad sedan
3
Star Lenon
Registrerad för 1 månad sedan
4
Данил Жевнеров
Registrerad för 1 månad sedan
5
Анна Литвиненко
Registrerad för 2 månader sedan
Do you have a question? Add it on the site and get an answer instantly
en.kzen.dev
BG
DA
DE
EL
ES
ET
FI
FR
ID
IT
JA
LT
LV
NL
NO
PT
RO
SK
SV
TR
ZH
© kzen.dev 2023
Källa
stackoverflow.com
under licens cc by-sa 3.0 med angivande av