For-each over an array in JavaScript

Jak mogę zapętlić wszystkie wpisy w tablicy używając JavaScript?

Myślałem, że to coś takiego:

forEach(instance in theArray)

Gdzie theArray jest moją tablicą, ale wydaje się to być błędne.

Author: Peter Mortensen, 2012-02-17

30 answers

TL; DR

  • Twoje najlepsze zakłady to zazwyczaj

    • A for-of pętla (tylko ES2015+)
    • forEach (spec | MDN) (w 1995 roku został wybrany do Izby Gmin.]}
    • prosty staromodny for pętla
    • (rzadko) for-in z zabezpieczeniami
  • Nie używaj for-in chyba że używasz go z zabezpieczeniami lub są przynajmniej świadomi, dlaczego może cię ugryźć.

  • Nie używaj map (spec | MDN) jeśli nie używasz zwracanej wartości map.
    (niestety ktoś tam uczy map jakby to było forEach - map's zadanie polega na utworzeniu nowej tablicy z wartości oryginalnej przekazanej przez funkcję mapowania, nie używaj jej tylko do iteracji)

Ale jest wiele więcej do odkrycia, Czytaj dalej...


JavaScript ma potężną semantykę do zapętlania tablic i obiektów podobnych do tablic. Podzieliłem odpowiedź na dwie części: opcje dla oryginalnych tablic i opcje dla rzeczy, które są tylko tablicami - , takich jak, takie jak obiekt arguments, Inne iterable objects (ES2015+), Kolekcje DOM i tak dalej.

Szybko zauważ, że możesz używać opcji ES2015 teraz , nawet na silnikach ES5, przez transpiling ES2015 do ES5. Szukaj "ES2015 transpiling" / "ES6 transpiling", aby uzyskać więcej informacji...

Dobra, spójrzmy na nasze opcje:

Dla Rzeczywistych Tablic

Masz trzy opcje w ECMAScript 5 ("ES5"), wersji najbardziej obecnie obsługiwanej, i dwie dodatkowe dodane w ECMAScript 2015 ("ES2015", "ES6"):

  1. użycie forEach i pokrewne (ES5+)
  2. użyj prostej for pętli
  3. użycie for-in poprawnie
  4. Nie jest to jednak możliwe, ponieważ nie jest to możliwe.]} W tym celu należy użyć iteratora w sposób jawny (ES2015+).]}

Szczegóły:

1. Użycie forEach i pokrewne

W dowolnym nowoczesnym środowisku (a więc nie IE8), gdzie masz dostęp do Array funkcji dodanych przez ES5 (bezpośrednio lub za pomocą polyfills), możesz użyć forEach (spec | MDN):

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

forEach akceptuje oddzwanianie funkcja i, opcjonalnie, wartość do użycia jako this podczas wywoływania tego wywołania zwrotnego (nie używana powyżej). Wywołanie zwrotne jest wywoływane dla każdego wpisu w tablicy, w kolejności, pomijając nieistniejące wpisy w rzadkich tablicach. Chociaż użyłem tylko jednego argumentu powyżej, wywołanie zwrotne jest wywoływane z trzema: wartością każdego wpisu, indeksem tego wpisu i odniesieniem do tablicy, którą iterujesz (na wypadek, gdyby twoja funkcja nie miała go pod ręką).

Chyba że obsługujesz przestarzałe przeglądarki podobnie jak IE8 (który netapps wykazuje nieco ponad 4% udziału w rynku od tego napisania we wrześniu 2016), możesz szczęśliwie używać forEach na stronie ogólnego przeznaczenia bez podkładki. Jeśli potrzebujesz obsługiwać przestarzałe przeglądarki, shimming/polyfilling forEach jest łatwo zrobić (wyszukaj "ES5 shim" dla kilku opcji).

forEach ma tę zaletę, że nie musisz deklarować zmiennych indeksujących i wartości w zakresie zawierającym, ponieważ są one dostarczane jako argumenty funkcji iteracji, a więc ładnie dopasowane do tej iteracji.

Jeśli martwisz się o koszt wywołania funkcji dla każdego wpisu tablicy, nie bądź; details.

Dodatkowo, forEach jest funkcją "loop through them all", ale ES5 zdefiniował kilka innych przydatnych funkcji "work your way through the array and do things", w tym:

  • every (zatrzymuje zapętlanie przy pierwszym zwrocie wywołania zwrotnego false lub coś w tym stylu falsey)
  • some (zatrzymuje zapętlanie przy pierwszym zwrocie wywołania zwrotnego true lub coś prawdziwego)
  • filter (tworzy nową tablicę zawierającą elementy, w których funkcja filtra zwraca true i pomija te, w których zwraca false)
  • map (tworzy nową tablicę z wartości zwracanych przez wywołanie zwrotne)
  • reduce (buduje wartość przez wielokrotne wywołanie wywołania zwrotnego, przechodząc w poprzednim wartości; szczegóły można znaleźć w specyfikacji; przydatne do sumowania zawartości tablicy i wielu innych rzeczy)
  • reduceRight (podobnie jak reduce, ale działa w porządku malejącym, a nie rosnącym) [158]}

2. Użyj prostej pętli for

Czasami stare sposoby są najlepsze:

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

Jeśli długość tablicy nie zmieni się podczas pętli, a jest w kodzie wrażliwym na wydajność (mało prawdopodobne), nieco bardziej skomplikowana wersja chwytając długość z przodu może być tiny trochę szybciej:

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

I/lub liczenie wstecz:

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

Ale z nowoczesnymi silnikami JavaScript, rzadko trzeba wycisnąć ten ostatni kawałek soku.

W ES2015 i nowszych możesz ustawić zmienne indeks i wartość lokalnie w pętlifor:

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"
}

I kiedy to robisz, nie tylko value ale także W przypadku pętli, w której nie ma żadnej pętli, nie jest to możliwe, ponieważ w pętli tej nie ma żadnej pętli, a w pętli tej nie ma żadnej pętli.]}

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>

Jeśli masz pięć div, dostaniesz "Index is: 0", jeśli klikniesz pierwszy i "Index is: 4", Jeśli klikniesz ostatni. To działa nie jeśli używasz var zamiast let.

3. Użycie for-in poprawnie

Dostaniesz ludzi kazanie Ci używać for-in, ale to nie jest to, co for-in jest dla. for-in pętli przez wylicz właściwości obiektu , a nie indeksy tablicy. kolejność nie jest gwarantowana , nawet w ES2015 (ES6). ES2015 + definiuje kolejność właściwości obiektu (poprzez [[OwnPropertyKeys]], [[Enumerate]], i rzeczy, które ich używają jak Object.getOwnPropertyKeys), ale nie zdefiniowano, że for-in będzie postępować zgodnie z tą kolejnością; jednak ES2020 to zrobił. (Szczegóły w ta druga odpowiedź.)

Jedynymi prawdziwymi przypadkami użyciafor-in na tablicy są:

  • to sparse tablice z masywne luki w nim, lub
  • używasz właściwości nieelementowych i chcesz umieścić je w pętli

Patrząc tylko na pierwszy przykład: możesz użyć for-in, aby odwiedzić te rzadkie elementy tablicy, jeśli użyjesz odpowiednich zabezpieczenia:

// `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]);
    }
}

Zwróć uwagę na trzy kontrole:

  1. Że obiekt posiada swoją własność własną o tej nazwie (nie taką, którą dziedziczy po swoim prototypie), oraz

  2. Że kluczem są wszystkie cyfry dziesiętne (np. normalna forma ciągu, a nie notacja naukowa) oraz

  3. Że wartość klucza przy wymuszeniu do liczby wynosi w specyfikacji . Pozostałe liczby (liczby niezliczone, liczby ujemne, liczby większe niż 2^32 - 2) nie są indeksami tablicowymi. Powodem jest 2^32 - 2 czy to sprawia, że największa wartość indeksu jest niższa niż 2^32 - 1, jest to maksymalna wartość, jaką może mieć tablica length. (Np. długość tablicy mieści się w 32-bitowej niepodpisanej liczbie całkowitej.) (rekwizyty dla Robga za wskazanie w komentarzu na moim blogu że mój poprzedni test nie był całkiem dobry.)

Nie zrobiłbyś tego w kodzie inline, oczywiście. Napisałbyś funkcję użytkową. Być może:

// 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. W tym celu należy użyć iteratora.]}

ES2015 dodał Iteratory do JavaScript. Najprostszym sposobem użycia iteratorów jest nowa Instrukcja for-of. Wygląda to tak:

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

Pod kołdrą, że pobiera iterator z tablicy i pętli przez nią, pobierając z niej wartości. Nie ma problemu, jaki ma użycie for-in, ponieważ używa iteratora zdefiniowanego przez obiekt (tablicę), a tablice definiują, że ich Iteratory są iteracyjne poprzez ich wpisy (Nie ich właściwości). W przeciwieństwie do for-in W ES5, kolejność odwiedzania wpisów jest kolejnością liczbową ich indeksów.

5. Jawnie używaj iteratora (ES2015+)

Czasami warto użyć iteratora jawnie . To też możesz zrobić, chociaż jest o wiele bardziej clunkierne niż for-of. Wygląda to tak:

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

Iterator jest obiektem pasującym do definicji iteratora w specyfikacji. Jej metoda next zwraca nowy obiekt wynikowy za każdym razem, gdy go wywołasz. Obiekt wynikowy ma właściwość done, informującą o tym, czy został wykonany, oraz właściwość value z wartością dla tej iteracji. (done jest opcjonalne, jeśli byłoby false, value jest opcjonalne, jeśli byłoby undefined.)

W zależności od iteratora znaczenie

Jest różne; tablice obsługują (przynajmniej) trzy funkcje zwracające Iteratory:

  • values(): to jest ten, którego użyłem powyżej. Zwraca iterator, gdzie każdy value jest wpisem tablicy dla tej iteracji ("a", "b", i "c" w przykładzie wcześniejszym).
  • keys(): zwraca iterator, w którym każdy value jest kluczem do tej iteracji(więc dla naszego a powyżej, to będzie "0", następnie "1", następnie "2").
  • entries(): zwraca iterator, gdzie każdy value jest tablicą w postaci [key, value] dla tej iteracji.

Dla Obiektów Podobnych Do Tablicy

Oprócz prawdziwych tablic, istnieją również podobne do tablicy obiekty, które mają właściwość length oraz właściwości o nazwach numerycznych: NodeList instancje, obiekt arguments, itd. Jak pętli przez ich zawartość?

Użyj dowolnej z powyższych opcji dla tablic

[146]}przynajmniej niektóre, a być może Większość lub nawet wszystkie powyższe podejścia do tablicy często stosują się równie dobrze do obiektów podobnych do tablicy: [149]}
  1. Use forEach and related (ES5+)

    Różne funkcje na Array.prototype są "celowo ogólne" i mogą być zwykle używane na obiektach podobnych do tablicy poprzez Function#call lub Function#apply. (Zobacz zastrzeżenie dla obiekt dostarczony przez hosta na końcu tej odpowiedzi, ale jest to rzadki problem.)

    Załóżmy, że chcesz użyć forEach na Node'S childNodes właściwość. Zrobiłbyś to:

     Array.prototype.forEach.call(node.childNodes, function(child) {
         // Do something with `child`
     });
    

    Jeśli zamierzasz robić to często, możesz chcieć pobrać kopię referencji funkcji do zmiennej w celu ponownego użycia, np.:

     // (This is all presumably in some scoping function)
     var forEach = Array.prototype.forEach;
    
     // Then later...
     forEach.call(node.childNodes, function(child) {
         // Do something with `child`
     });
    
  2. Użyj prostej pętli for

    Oczywiście, prosta for pętla ma zastosowanie do tablicy obiektów.

  3. Użycie for-in prawidłowo

    for-in z tymi samymi zabezpieczeniami jak w przypadku tablicy powinny działać również z obiektami podobnymi do tablicy; może mieć zastosowanie zastrzeżenie dla obiektów dostarczanych przez host na #1 powyżej.

  4. Use for-of (use an iterator implicite) (ES2015+)

    for-of używa iteratora dostarczonego przez obiekt (jeśli istnieje). Obejmuje to obiekty dostarczone przez hosta. Na przykład Specyfikacja NodeList z {[126] } została zaktualizowana, aby wspierać iterację. Spec dla HTMLCollection z getElementsByTagName nie było.

  5. Jawnie używaj iteratora (ES2015+)

    Zobacz #4.

Utwórz prawdziwą tablicę

Innym razem możesz chcieć przekonwertować obiekt podobny do tablicy na tablicę rzeczywistą. Jest to zaskakująco łatwe:

  1. Użyj metody slice tablic

    Możemy użyj slice metoda tablic, która podobnie jak inne metody wymienione powyżej jest "celowo ogólna" i dlatego może być używana z obiektami typu tablica, jak poniżej:

     var trueArray = Array.prototype.slice.call(arrayLikeObject);
    

    Więc na przykład, jeśli chcemy przekonwertować NodeList do tablicy prawdziwej, możemy to zrobić:

     var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
    

    Zobacz Zastrzeżenie dla obiektów dostarczanych przez host poniżej. W szczególności, zauważ, że to nie powiedzie się w IE8 i wcześniejszych, które nie pozwalają używać obiektów dostarczanych przez host jako this jak to.

  2. Użyj składni spread (...)

    Możliwe jest również użycie składni rozproszonej ES2015 z silnikami JavaScript, które obsługują tę funkcję. Podobnie jak for-of, używa iteratora dostarczonego przez obiekt (patrz #4 w poprzedniej sekcji):

     var trueArray = [...iterableObject];
    

    Na przykład, jeśli chcemy przekonwertować NodeList do prawdziwej tablicy, ze składnią spread staje się to dość zwięzłe:

     var divs = [...document.querySelectorAll("div")];
    
  3. Użycie Array.from

    Array.from (spec) | (MDN) (ES2015+, ale łatwo polyfilled) tworzy tablicę z obiektu podobnego do tablicy, opcjonalnie przekazując wpisy jako pierwsze przez funkcję mapowania. Więc:

     var divs = Array.from(document.querySelectorAll("div"));
    

    Lub jeśli chcesz uzyskać tablicę nazw znaczników elementów z podaną klasą, użyj funkcji mapowania:

     // Arrow function (ES2015):
     var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
    
     // Standard function (since `Array.from` can be shimmed):
     var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
         return element.tagName;
     });
    

Zastrzeżenie dla obiektów dostarczanych przez hosta

Jeśli używasz Array.prototype funkcji z host-provided array-like objects( listy DOM i inne rzeczy dostarczane przez przeglądarkę, a nie silnik JavaScript), musisz upewnić się, że testujesz w swoich środowiskach docelowych, aby upewnić się, że obiekt host-provided zachowuje się poprawnie. Większość zachowuje się prawidłowo (teraz), ale ważne jest, aby przetestować. Powodem jest to, że większość metod Array.prototype, których prawdopodobnie chcesz użyć, opiera się na obiekcie dostarczonym przez hosta, dając szczerą odpowiedź na streszczenie [[HasProperty]] operacja. W momencie pisania tego tekstu przeglądarki wykonują bardzo dobrą robotę, ale specyfikacja 5.1 pozwoliła na to, że obiekt dostarczany przez host może nie być uczciwy. Jest w §8.6.2, kilka akapitów pod dużą tabelą na początku tej sekcji), Gdzie jest napisane:

Obiekty hosta mogą zaimplementować te wewnętrzne metody w dowolny sposób, chyba że określono inaczej; na przykład, jedną z możliwości jest to, że [[Get]] i [[Put]] dla konkretnego obiektu hosta rzeczywiście pobierają i przechowuje wartości właściwości, ale [[HasProperty]] zawsze generuje false.

(nie mogłem znaleźć równoważnej wersji w specyfikacji ES2015, ale na pewno nadal tak jest.) Ponownie, w momencie pisania tego typu obiektów w nowoczesnych przeglądarkach [NodeList instancje, na przykład] robią obsługują [[HasProperty]] poprawnie, ale ważne jest, aby przetestować.)

 7318
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-09 16:04:50

Uwaga : ta odpowiedź jest beznadziejnie nieaktualna. Aby uzyskać bardziej nowoczesne podejście, spójrz na metody dostępne w tablicy . Metody zainteresowań mogą być:

  • forEach
  • Mapa
  • filtr
  • zip
  • reduce
  • każdy
  • niektóre

Standardowy sposób iteracji tablicy w JavaScript to vanilla for - loop:

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

Należy jednak pamiętać, że takie podejście jest dobre tylko wtedy, gdy masz gęsta tablica, a każdy indeks jest zajęty przez element. Jeśli tablica jest rzadka, to możesz napotkać problemy z wydajnością z tym podejściem, ponieważ będziesz iteracją wielu indeksów, które nie istnieją naprawdę w tablicy. W tym przypadku pętla for .. in może być lepszym pomysłem. jednakże , musisz użyć odpowiednich zabezpieczeń, aby upewnić się, że działają tylko pożądane właściwości tablicy (tzn. elementy tablicy), ponieważ pętla for..in - będzie również wyliczona w starsze przeglądarki, lub jeśli dodatkowe właściwości są zdefiniowane jako enumerable.

W ECMAScript 5 w prototypie tablicy znajdzie się metoda forEach, ale nie jest ona obsługiwana w starszych przeglądarkach. Aby móc używać go konsekwentnie, musisz mieć środowisko, które go wspiera (na przykład Node.js dla JavaScript po stronie serwera), lub użyć "Polyfill". Polyfill dla tej funkcjonalności jest jednak banalny, a ponieważ sprawia, że kod jest łatwiejszy do odczytania, jest to dobry polyfill to include.

 535
Author: PatrikAkerstrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 19:57:21

Jeśli używasz jQuery biblioteki, możesz użyć jQuery.każdy:

$.each(yourArray, function(index, value) {
  // do your stuff here
});

EDIT:

Jak na pytanie, użytkownik chce kod w javascript zamiast jquery więc edycja jest

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}
 251
Author: Poonam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 05:17:40

Pętla do tyłu

Myślę, że odwrotność dla pętli zasługuje na wzmiankę tutaj:

for (var i = array.length; i--; ) {
     // process array[i]
}

Zalety:

  • nie musisz deklarować tymczasowej zmiennej len ani porównywać z array.length przy każdej iteracji, z których każda może być minutową optymalizacją.
  • usuwanie rodzeństwa Z DOM w odwrotnej kolejności jest zwykle bardziej efektywne . (Przeglądarka musi mniej przesuwać elementy w swojej wewnętrznej tablice.)
  • jeśli zmodyfikujesz tablicę podczas zapętlania, przy indeksie i lub po nim (na przykład usuniesz lub wstawisz element w array[i]), wtedy pętla do przodu pominie element, który został przesunięty w lewo na pozycję i , lub ponownie przetworzy i {54]} ten element, który został przesunięty w prawo. W tradycyjnej pętli for można zaktualizować i , aby wskazać następny element, który wymaga przetworzenia - 1, ale po prostu odwrócenie kierunku iteracji jest często prostsze i bardziej eleganckie rozwiązanie .
  • podobnie, podczas modyfikowania lub usuwania zagnieżdżonych elementów DOM, przetwarzanie w odwrotnej kolejności może obejść błędy . Na przykład rozważ modyfikację innerHTML węzła nadrzędnego przed obsługą jego dzieci. Do czasu osiągnięcia węzła potomnego zostanie on odłączony od DOM, po zastąpieniu go nowo utworzonym węzłem potomnym, gdy rodzic został napisany innerHTML.
  • jest krótszy aby wpisać, i Czytaj , niż niektóre z innych dostępnych opcji. Chociaż przegrywa z forEach() i z for ... of ES6.

Wady:

  • przetwarza elementy w odwrotnej kolejności. Jeśli budujesz nową tablicę z wyników lub drukujesz rzeczy na ekranie, naturalnie wynik zostanie odwrócony w stosunku do pierwotnej kolejności.
  • wielokrotne wstawianie rodzeństwa do domu jako pierwszego dziecka w celu zachowania porządku jest mniej efektywny . (Przeglądarka musiałaby ciągle przesuwać rzeczy w prawo.) Aby tworzyć węzły DOM sprawnie i w porządku, wystarczy zapętlić do przodu i dołączyć jak zwykle (a także użyć "fragmentu dokumentu").
  • odwrotna pętla jest myląca dla młodszych programistów. (Można uznać, że zaletą, w zależności od perspektywy.)

Czy zawsze powinienem go używać?

Niektórzy programiści używają odwrotnej pętli domyślnie, chyba że istnieje dobry powód pętla do przodu.

Chociaż wzrost wydajności jest zwykle nieznaczny, to w pewnym sensie krzyczy:]}

"po prostu zrób to do każdego elementu na liście, nie obchodzi mnie kolejność!"

Jednak w praktyce jest to Nie w rzeczywistości wiarygodne wskazanie intencji, ponieważ jest to nieodróżnialne od tych przypadków, gdy do dbać o porządek i naprawdę zrobić potrzeba zapętlić w odwrotnej kolejności. Więc faktycznie potrzebny byłby inny konstrukt, aby dokładnie wyrazić intencję" don 't care", coś obecnie niedostępnego w większości języków, w tym ECMAScript, ale który można by nazwać na przykład forEachUnordered().

Jeśli kolejność nie ma znaczenia, a wydajność jest problemem (w najbardziej wewnętrznej pętli silnika gry lub animacji), to może być dopuszczalne użycie pętli odwrotnej Dla jako wzorca. Pamiętaj tylko, że zobaczenie pętli odwrotnej dla w istniejącym kodzie Nie musi oznaczać , że kolejność nieistotna!

Lepiej było użyć forEach ()

Ogólnie dla kodu wyższego poziomu, gdzie przejrzystość i bezpieczeństwo są większe obawy, wcześniej zalecałem użycie Array::forEach jako domyślny wzorzec pętli (chociaż obecnie wolę używać for..of). W przeciwieństwie do pętli odwrotnej, pętla odwrotna nie jest pętlą odwrotną.]}

  • to jest bardziej czytelne.
  • oznacza to, że i nie zostanie przesunięty wewnątrz bloku (co jest zawsze możliwą niespodzianką ukrywającą się w długich pętlach for i while).
  • daje Ci swobodę zamykania.
  • zmniejsza wyciek zmiennych lokalnych i przypadkowe kolizje z (i mutacji) zmiennych zewnętrznych.

Wtedy, gdy widzisz pętlę odwrotną dla kodu, jest to wskazówka, że jest ona odwrócona z ważnego powodu (być może z jednego z powodów opisanych powyżej). A widzenie tradycyjnej pętli for For może wskazywać, że zmiana może mieć miejsce.

(jeśli dyskusja na temat intencji nie ma dla Ciebie sensu, wtedy ty i twój kod możecie skorzystać z wykładu Crockforda na temat programowania Style & Your Brain .)

Jest teraz jeszcze lepiej używać dla..of!

Toczy się dyskusja o tym, czy for..of czy forEach() są lepsze:

  • Dla maksymalnej obsługi przeglądarki, for..of wymaga polyfill dla iteratorów, co sprawia, że aplikacja jest nieco wolniejsza i nieco większy do pobrania.

  • Z tego powodu (i zachęcić do korzystania z map ifilter), niektóre front-end style guides ban for..of całkowicie!

  • Powyższe obawy nie dotyczą jednak Node.aplikacje js, gdzie for..of jest teraz dobrze obsługiwane.

  • A ponadto await nie działa wewnątrz forEach(). Użycie for..of jest najczystszym wzorem w tym przypadku.

Osobiście, Ja mają tendencję do używania tego, co wygląda najłatwiej przeczytać, chyba że wydajność lub minifikacja stała się głównym problemem. Więc w dzisiejszych czasach wolę używać for..of zamiast forEach(), ale zawsze będę używać map lub filter lub find lub some w stosownych przypadkach. (Ze względu na kolegów rzadko używam reduce.)


Jak to działa?
for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

Zauważysz, że i-- jest klauzulą środkową (gdzie zwykle widzimy porównanie) i ostatnią klauzulą jest pusty (gdzie zwykle widzimy i++). Oznacza to, że i-- jest również używany jako warunek dla kontynuacji. Co najważniejsze, jest ona wykonywana i sprawdzana przed każdą iteracją.

  • Jak może zacząć się od array.length bez eksplodowania?

    Ponieważ i-- uruchamia przed każdą iteracją, na pierwszej iteracji będziemy mieli dostęp do elementu w array.length - 1, który unika wszelkich problemów z Array-out-of-bounds undefined pozycji.

  • Dlaczego nie przestaje iteracji przed indeksem 0?

    Pętla zatrzyma iterację, gdy warunek i-- obliczy wartość FALSE ' a (gdy Da 0).

    Sztuczka polega na tym, że w przeciwieństwie do --i, Operator końcowy i-- zmniejsza i, ale daje wartość przed dekret. Twoja konsola może to zademonstrować:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    Więc na ostatecznej iteracji, i był wcześniej 1 i wyrażenie i-- zmienia je na 0 ale faktycznie daje 1 (truthy), a więc warunek mija. W następnej iteracji i-- zmienia i na -1 ale plony 0 (false), powodując natychmiastowe opuszczenie dolnej części pętli.

    W tradycyjnym forward for loop, i++ i ++i są wymienne (jak wskazuje Douglas Crockford). Jednak w odwrotnej pętli for, ponieważ nasz dekrement jest również naszym wyrażeniem warunkowym, musimy trzymać się i-- jeśli chcemy przetworzyć element w indeksie 0.


Ciekawostki

Niektórzy ludzie lubią narysować małą strzałkę na odwrocie for pętlę i zakończyć mrugnięciem oka:

for (var i = array.length; i --> 0 ;) {

/ align = "center" bgcolor = "# e0ffe0 " / cesarz chin / / align = center /

 130
Author: joeytwiddle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-20 04:11:06

Niektóre języki C używają foreach do pętli przez wyliczenia. W JavaScript odbywa się to za pomocą for..in Struktura pętli :

var index,
    value;
for (index in obj) {
    value = obj[index];
}
Jest pewien haczyk. for..in będzie przeszukiwać każdy z elementów obiektu oraz elementy znajdujące się na jego prototypie. Aby uniknąć odczytu wartości dziedziczonych przez prototyp obiektu, po prostu sprawdź, czy właściwość należy do obiektu:
for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

Dodatkowo, ECMAScript 5 dodał forEach metoda Array.prototype, która może być użyta do wyliczenia tablicy za pomocą kalbacka (polyfill jest w dokumentach, więc nadal możesz go używać w starszych przeglądarkach):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

Ważne jest, aby pamiętać, że Array.prototype.forEach nie pęka, gdy callback zwraca false. jQuery i podkreślenie.js zapewniają własne wariacje na each, aby zapewnić pętle, które mogą być zwarte.

 90
Author: zzzzBov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-13 01:18:21

Jeśli chcesz zapętlić tablicę, użyj standardowej trzyczęściowej pętli for.

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

Możesz uzyskać kilka optymalizacji wydajności poprzez buforowanie myArray.length lub iterację nad nim wstecz.

 48
Author: Quentin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-17 13:55:46

Jeśli nie masz nic przeciwko opróżnieniu tablicy:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

x będzie zawierać ostatnią wartość y i zostanie usunięta z tablicy. Możesz również użyć shift(), która da i usunie pierwszy element z y.

 37
Author: gaby de wilde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-30 18:37:32

Wiem, że to stary post, a jest już tak wiele świetnych odpowiedzi. Dla większej kompletności pomyślałem, że dorzucę jeszcze jedną używając AngularJS. Oczywiście, dotyczy to tylko jeśli używasz Angular, oczywiście, niemniej jednak chciałbym to ująć i tak.

angular.forEach pobiera 2 argumenty i opcjonalny trzeci argument. Pierwszym argumentem jest obiekt (tablica) do iteracji, drugim argumentem jest funkcja iteratora, a opcjonalnym trzecim argumentem jest obiekt kontekst (w zasadzie określany wewnątrz pętli jako "this".

Istnieją różne sposoby wykorzystania pętli foreach kątowej. Najprostszym i prawdopodobnie najczęściej używanym jest

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

Innym sposobem, który jest przydatny do kopiowania elementów z jednej tablicy do drugiej jest

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);
Jednak nie musisz tego robić, możesz po prostu wykonać następujące czynności i jest to równoważne z poprzednim przykładem:]}
angular.forEach(temp, function(item) {
    temp2.push(item);
});

Teraz są plusy i minusy używania funkcji angular.forEach w przeciwieństwie do wbudowanej w pętli o smaku waniliowym for.

Plusy

  • łatwa czytelność
  • łatwa pisownia
  • jeśli jest dostępny, angular.forEach użyje pętli ES5 forEach. Teraz przejdę do efficiency w sekcji cons, ponieważ pętle forEach są dużo wolniejsze niż pętle for. Wspominam o tym jako profesjonalista, ponieważ miło jest być konsekwentnym i ustandaryzowanym.

Rozważ następujące 2 zagnieżdżone pętle, które robią dokładnie to samo. Powiedzmy, że my mają 2 tablice obiektów i każdy obiekt zawiera tablicę wyników, z których każdy ma właściwość Value, która jest ciągiem znaków (lub cokolwiek innego). I powiedzmy, że musimy iterować nad każdym z wyników i jeśli są równe, wykonaj jakąś akcję: {]}

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

Przyznaję, że jest to bardzo prosty hipotetyczny przykład, ale napisałem triple embedded dla pętli za pomocą drugiego podejścia i było to Bardzo trudne do odczytania i napisania Materia.

Cons

  • efektywność. angular.forEach, a rodzime forEach, w tym przypadku, są zarównoo wiele wolniejsze niż normalna for pętla....o 90% wolniej . W przypadku dużych zbiorów danych najlepiej trzymać się natywnej pętli for.
  • brak wsparcia break, continue, lub return. continue jest rzeczywiście wspierany przez " wypadek", aby kontynuować w angular.forEach wystarczy umieścić return; w funkcji jak angular.forEach(array, function(item) { if (someConditionIsTrue) return; });, co spowoduje, że kontynuuj z funkcji dla tej iteracji. Wynika to również z faktu, że natywny forEach również nie obsługuje break lub continue.

Jestem pewien, że są też inne plusy i minusy, i nie krępuj się dodawać dowolnych, które uznasz za odpowiednie. Czuję, że, podsumowując, jeśli potrzebujesz wydajności, trzymaj się tylko natywnej pętli for dla swoich potrzeb pętli. Ale jeśli twoje zbiory danych są mniejsze i pewna wydajność jest w porządku, aby zrezygnować w zamian za czytelność i pisowalność, więc rzuć angular.forEach w tego niegrzecznego chłopca.

 36
Author: user2359695,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 22:56:52

A forEach implementation (Zobacz w jsFiddle):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);
 33
Author: nmoliveira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 12:22:55

Od ECMAScript 6:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

Gdzie of unika dziwności związanych z in i sprawia, że działa jak pętla {[3] } dowolnego innego języka, a let wiąże i wewnątrz pętli w przeciwieństwie do funkcji.

Klamry ({}) można pominąć, gdy istnieje tylko jedno polecenie (np. w powyższym przykładzie).

 32
Author: Zaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-12 05:12:07

Prawdopodobnie pętla for(i = 0; i < array.length; i++) nie jest najlepszym wyborem. Dlaczego? Jeśli masz to:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

Metoda wywoła z array[0] do array[2]. Po pierwsze, spowoduje to odniesienie do zmiennych, których nawet nie masz, po drugie, nie będziesz miał zmiennych w tablicy, a po trzecie, spowoduje to, że kod będzie odważniejszy. Spójrz tutaj, to jest to, czego używam:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

I jeśli chcesz, aby to była funkcja, możesz to zrobić:

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

Jeśli chcesz złamać, trochę więcej logika:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

Przykład:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

Zwraca:

//Hello
//World
//!!!
 30
Author: Federico Piragua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-08 10:49:27

Istnieją trzy implementacje foreach w jQuery w następujący sposób.

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3
 30
Author: Rajesh Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-08 10:50:06

Łatwym rozwiązaniem byłoby teraz użycie podkreślenia .biblioteka js . Zapewnia wiele przydatnych narzędzi, takich jak {[1] } i automatycznie deleguje zadanie do natywnego forEach, jeśli jest dostępne.

Przykład kodu Jak to działa to:

var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});

Zobacz też

 29
Author: Micka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-30 22:23:09

Nie ma żadnej pętli for each w natywnym JavaScript. Możesz użyć bibliotek, aby uzyskać tę funkcjonalność (polecam Underscore.js), użyj prostej {[3] } W pętli.

for (var instance in objects) {
   ...
}

Należy jednak pamiętać, że mogą być powody, aby użyć jeszcze prostszej pętli for (Zobacz pytanie o przepełnienie stosuDlaczego jest za pomocą "for...in" z iteracją tablicy taki zły pomysł?)

var instance;
for (var i=0; i < objects.length; i++) {
    var instance = objects[i];
    ...
}
 24
Author: joidegn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:36

Jest to iterator dla listy nieliniowej, gdzie indeks zaczyna się od 0, co jest typowym scenariuszem w przypadku dokumentu.getElementsByTagName lub document.querySelectorAll)

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

Przykłady użycia:

Przykład #1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

Przykład #2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

Każdy znacznik P dostaje class="blue"

Przykład #3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

Co drugi znacznik P dostaje class="red">

Przykład #4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

I wreszcie pierwsze 20 niebieskich znaczników p zmienia się na zielone

Uwaga Podczas używania ciągu znaków jako funkcji: funkcja jest tworzona poza kontekstem i powinna być używana tylko wtedy, gdy masz pewność zakresu zmiennych. W przeciwnym razie lepiej przekazać funkcje, w których zasięg jest bardziej intuicyjny.

 23
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-29 12:28:20

Istnieje kilka sposobów pętli przez tablicę w JavaScript, jak poniżej:

Dla - jest to najczęstszy. Pełny blok kodu do zapętlania

var languages = ["Java", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

While - pętla while warunek jest skończony. Wydaje się być najszybszą pętlą

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

Do / while - również Pętla przez blok kodu, gdy warunek jest true, będzie działać co najmniej one time

var text = ""
var i = 0;

do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);

document.getElementById("example").innerHTML = text;
<p id="example"></p>

Pętle funkcjonalne - forEach, map, filter, również reduce (pętli przez funkcję, ale są one używane, jeśli trzeba zrobić coś z tablicy, itp.

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

Aby uzyskać więcej informacji i przykładów na temat programowania funkcyjnego na tablicach, zajrzyj do wpisu na bloguprogramowanie funkcjonalne w JavaScript: mapowanie, filtrowanie i redukowanie.

 22
Author: Alireza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-22 23:32:48

ECMAScript 5 (Wersja Na JavaScript) do pracy z tablicami:

ForEach - iteruje każdy element w tablicy i robi z każdym elementem wszystko, czego potrzebujesz.

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is #" + (index+1) + " in the musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

W przypadku, bardziej zainteresowany działaniem na tablicy przy użyciu jakiejś wbudowanej funkcji.

Map - tworzy nową tablicę z wynikiem funkcji callback. Ta metoda jest dobra do użycia, gdy trzeba sformatować elementy tablicy.

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

Reduce - jako nazwa mówi, że zmniejsza tablicę do pojedynczej wartości przez wywołanie danej funkcji przechodzącej w bieżącym elemencie i wyniku poprzedniego wykonania.

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

Every - zwraca true lub false, jeśli wszystkie elementy w tablicy przeszły test w funkcji callback.

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];
ages.every(function(elem) {
  return elem >= 18;
});

// Output: false

Filter - bardzo podobny do każdego z wyjątkiem, że filtr zwraca tablicę z elementami, które zwracają true do podanej funkcji.

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]
 20
Author: Anil Kumar Arya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 20:55:31

Nie ma wbudowanej możliwości włamania się forEach. Aby przerwać wykonanie użyj Array#some Jak poniżej:

[1,2,3].some(function(number) {
    return number === 1;
});

To działa, ponieważ some zwraca true tak szybko, jak każde wywołanie zwrotne, wykonane w kolejności tablicy, zwraca true, co powoduje zwarcie wykonania reszty. Oryginalna Odpowiedź zobacz prototyp tablicy dla niektórych

 19
Author: Priyanshu Chauhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:59

Chciałbym również dodać to jako kompozycję odwrotnej pętli i odpowiedź powyżej dla kogoś, kto chciałby tę składnię też.

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

Plusy:

Korzyści z tego: masz referencję już w pierwszym, jak, że nie będzie musiał być zadeklarowany później z innej linii. Jest to przydatne przy zapętlaniu przez tablicę obiektów.

Wady:

Zostanie przerwane, gdy Referencja będzie false-False (undefined, etc.). Może być stosowany jako ale przewaga. Byłoby to jednak nieco trudniejsze do odczytania. A także w zależności od przeglądarki można go "nie" zoptymalizować, aby działał szybciej niż oryginalna.

 16
Author: Volkan Seçkin Akbayır,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-28 16:08:21

JQuery way using $.map:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];
 12
Author: Daniel W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-01 11:15:26

Używanie pętli z operatorem rozproszonym ECMAScript 6 destrukcji i

Destrukcja i użycie operatora rozprzestrzeniania okazały się dość przydatne dla początkujących w ECMAScript 6 jako bardziej czytelny / estetyczny, chociaż niektórzy weterani JavaScript mogą uznać to za bałagan. Juniorzy lub inni ludzie mogą uznać to za przydatne.

Poniższe przykłady będą używać for...of oświadczenie i .forEach metoda.

Przykłady 6, 7 i 8 mogą być używane z dowolnymi pętlami funkcyjnymi, takimi jak .map, .filter, .reduce, .sort, .every, .some. Więcej informacji na temat tych metod można znaleźć w obiekcie Array .

Przykład 1: Normal for...of loop-żadnych sztuczek.

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

Przykład 2: podziel słowa na znaki

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);
}

Przykład 3: zapętlenie za pomocą key i value

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type:
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on Internet Explorer  unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

Przykład 4: Get object properties inline

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

Przykład 5: Get deep object properties of what you need

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

Przykład 6: to przykład 3 używany z .forEach

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

Przykład 7: to przykład 4 używany z .forEach

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions
// are required to be surrounded by parentheses
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

Przykład 8: To Przykład 5 używane z .forEach

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});
 10
Author: darklightcode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Najbardziej zbliżonym sposobem do twojego pomysłu byłoby użycie Array.forEach(), które akceptuje funkcję zamknięcia, która będzie wykonywana dla każdego elementu tablicy.

myArray.forEach(
  (item) => {
    // Do something
    console.log(item);
  }
);

Innym realnym sposobem byłoby użycie Array.map(), które działa w ten sam sposób, ale również pobiera wszystkie zwracane wartości i zwraca je w nowej tablicy( zasadniczo mapowanie każdego elementu na nowy), Tak:

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]
 8
Author: Ante Jablan Adamović,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-04 17:51:03

Składnia lambda zwykle nie działa w Internet Explorerze 10 lub poniżej.

Zwykle używam

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

Jeśli jesteś fanem jQuery i masz już uruchomiony plik jQuery, powinieneś odwrócić pozycje parametrów indeksu i wartości

$("#ul>li").each(function(**index, value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});
 7
Author: Murtuza Husain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 20:36:46

Możesz wywołać forEach Tak:

forEach będzie iteracją nad podaną tablicą i dla każdej iteracji będzie miała element, która przechowuje wartość tej iteracji. Jeśli potrzebujesz indeksu, możesz uzyskać bieżący indeks, przekazując i jako drugi parametr w funkcji callback dla forEach.

Foreach jest zasadniczo funkcją wysokiego rzędu, która przyjmuje inną funkcję jako swój parametr.

let theArray= [1,3,2];

theArray.forEach((element) => {
  // Use the element of the array
  console.log(element)
}

Wyjście:

1
3
2

Można również iterację nad tablicą taką jak to:

for (let i=0; i<theArray.length; i++) {
  console.log(i); // i will have the value of each index
}
 7
Author: Nouman Dilshad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-25 12:13:35

Jeśli chcesz użyć forEach(), będzie to wyglądało tak: -

theArray.forEach ( element => {
    console.log(element);
});

Jeśli chcesz użyć for(), będzie to wyglądało tak: -

for(let idx = 0; idx < theArray.length; idx++){
    let element = theArray[idx];
    console.log(element);
}
 6
Author: Harunur Rashid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-04 23:18:22

Jeśli chcesz zapętlić tablicę obiektów za pomocą funkcji strzałki:

let arr = [{name:'john', age:50}, {name:'clark', age:19}, {name:'mohan', age:26}];

arr.forEach((person)=>{
  console.log('I am ' + person.name + ' and I am ' + person.age + ' old');
})
 6
Author: subhashish negi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 20:04:07

Wydajność

Dzisiaj (2019-12-18) wykonuję test na moim macOS v10.13.6 (High Sierra), Na Chrome v 79.0, Safari v13.0. 4 i Firefox v71. 0 (64 bit) - wnioski dotyczące optymalizacji (i mikro-optymalizacja co zwykle nie warto wprowadzać go do kodu, ponieważ korzyści są niewielkie, ale złożoność kodu rośnie).

  • Wygląda jak tradycyjny for i (Aa ) jest dobrym wyborem do napisania szybkiego kodu na wszystkich przeglądarki.

  • Inne rozwiązania, takie jak for-of (Ad), wszystkie w grupie C. ... są zwykle 2-10 (i więcej) razy wolniejsze niż Aa , ale w przypadku małych tablic można ich używać - dla zwiększenia przejrzystości kodu.

  • Pętle o długości tablicy w pamięci podręcznej n (Ab, Bb, Be) są czasem szybsze, czasem nie. Prawdopodobnie Kompilatory automatycznie wykrywają tę sytuację i wprowadzają buforowanie. Różnice prędkości między wersje cached i no-cached ( Aa, Ba, Bd ) są około ~1%, więc wygląda na to, że introduce n jest mikro-optymalizacja.

  • i-- podobne rozwiązania, w których pętla zaczyna się od ostatniego elementu tablicy ( Ac, BC ) są zwykle ~30% wolniejsze od rozwiązań forward - prawdopodobnie powodem jest sposób działania pamięci podręcznej CPU - odczyt pamięci forward jest bardziej optymalny dla buforowania CPU). zaleca się, aby nie używać takich rozwiązania.

Szczegóły

W testach obliczamy sumę elementów tablicy. Wykonuję test dla małych tablic (10 elementów) i dużych tablic (1m elementów) i dzielę je na trzy grupy:

  • A - for testy
  • B - while testy
  • C - inne / alternatywne metody

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
//let arr = Array.from(Array(1000000), (x, i) => i%10);

function Aa(a, s=0) {
  for(let i=0; i<a.length; i++) {
    s += a[i];
  }
  console.log('Aa=', s);
}

function Ab(a, s=0) {
  let n = a.length;
  for(let i=0; i<n; i++) {
    s += a[i];
  }
  console.log('Ab=', s);
}

function Ac(a, s=0) {
  for(let i=a.length; i--;) {
    s += a[i];
  }
  console.log('Ac=', s);
}

function Ad(a, s=0) {
  for(let x of a) {
    s += x;
  }
  console.log('Ad=', s);
}

function Ae(a, s=0) {
  for(let i in a) if (a.hasOwnProperty(i)) {
    s += a[i];
  }
  console.log('Ae=', s);
}

function Ba(a, s=0) {
  let i = -1;
  while(++i < a.length) {
    s+= a[i];
  }
  console.log('Ba=', s);
}

function Bb(a, s=0) {
  let i = -1;
  let n = a.length;
  while(++i < n) {
    s+= a[i];
  }
  console.log('Bb=', s);
}

function Bc(a, s=0) {
  let i = a.length;
  while(i--) {
    s += a[i];
  }
  console.log('Bc=', s);
}

function Bd(a, s=0) {
  let i = 0;
  do {
    s+= a[i]
  } while (++i < a.length);
  console.log('Bd=', s);
}

function Be(a, s=0) {
  let i = 0;
  let n = a.length;
  do {
    s += a[i]
  } while (++i < n);
  console.log('Be=', s);
}

function Bf(a, s=0) {
  const it = a.values(); 
  let e;
  while (!(e = it.next()).done) { 
    s+= e.value; 
  }
  console.log('Bf=', s);
}

function Ca(a, s=0) {
  a.map(x => { s+=x });
  console.log('Ca=', s);
}

function Cb(a, s=0) {
  a.forEach(x => { s+=x });
  console.log('Cb=', s);
}

function Cc(a, s=0) {
  a.every(x => (s += x, 1));
  console.log('Cc=', s);
}

function Cd(a, s=0) {
  a.filter(x => { s+=x });
  console.log('Cd=',s);
}

function Ce(a, s=0) {
  a.reduce((z, c) => { s+=c }, 0);
  console.log('Ce=', s);
}

function Cf(a, s=0) {
  a.reduceRight((z, c) => { s += c }, 0);
  console.log('Cf=', s);
}

function Cg(a, s=0) {
  a.some(x => { s += x } );
  console.log('Cg=', s);
}

function Ch(a, s=0) {
  Array.from(a, x=> s += x);
  console.log('Cc=', s);
}


Aa(arr);
Ab(arr);
Ac(arr);
Ad(arr);
Ae(arr);

Ba(arr);
Bb(arr);
Bc(arr);
Bd(arr);
Be(arr);
Bf(arr);

Ca(arr);
Cb(arr);
Cc(arr);
Cd(arr);
Ce(arr);
Cf(arr);
Cg(arr);
Ch(arr);
<p style="color: red">This snippets only PRESENTS code used for benchmark - it not perform test itself</p>

Cross browser results

Wyniki dla wszystkich badanych przeglądarki

Tutaj wpisz opis obrazkaprzeglądarki * *

Tablica z 10 elementami

Wyniki dla Chrome. Możesz wykonać test na swojej maszynie tutaj .

Tutaj wpisz opis obrazka

Tablica z 1 000 000 elementów

Wyniki dla Chrome. Możesz wykonać test na swojej maszynie tutaj

Tutaj wpisz opis obrazka

 6
Author: Kamil Kiełczewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-08 19:17:34

Jeśli masz masywną tablicę powinieneś użyć iterators aby zyskać trochę wydajności. Iteratory są własnością pewnych kolekcji JavaScript (jak Map, Set, String, Array). Parzyste, for..of zastosowania iterator pod maską.

Iteratory zwiększają wydajność, pozwalając użytkować po kolei przedmioty z listy, tak jakby były strumieniem. Iterator wyróżnia się tym, jak przemierza kolekcja. Inne pętle muszą załadować całą kolekcję z przodu, aby iterować nad nią, podczas gdy iterator musi znać tylko bieżącą pozycję w kolekcji.

Dostęp do bieżącego elementu można uzyskać, wywołując metodę iteratora next. Następna metoda zwróci value bieżącej pozycji oraz boolean aby wskazać, kiedy dotarłeś do końca kolekcji. Poniżej przedstawiono przykład tworzenia iteratora z tablicy.

Przekształć zwykłą tablicę w iterator używając values() metoda jak ta:

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

Możesz również przekształcić zwykłą tablicę do iteratora za pomocą Symbol.iterator tak:

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

Możesz również przekształcić swoje zwykłe array W iterator tak:

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

Uwaga :

  • Iteratory są wyczerpujące w naturze.
  • obiekty nie są domyślnie iterable. Użycie for..in W takim przypadku, ponieważ zamiast wartości działa z kluczami.

Możesz przeczytać więcej o iteration protocol tutaj .

 5
Author: BlackBeard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-06 11:32:03

Zgodnie z nową, zaktualizowaną funkcją ECMAScript 6 (ES6) i ECMAScript 2015, możesz używać następujących opcji z pętlami:

Dla pętli

for(var i = 0; i < 5; i++){
  console.log(i);
}

// Output: 0,1,2,3,4

For...in pętle

let obj = {"a":1, "b":2}

for(let k in obj){
  console.log(k)
}

// Output: a,b

/ align = "left" / forEach()

let array = [1,2,3,4]

array.forEach((x) => {
  console.log(x);
})

// Output: 1,2,3,4

Za...of loops

let array = [1,2,3,4]

for(let x of array){
  console.log(x);
}

// Output: 1,2,3,4

Pętle While

let x = 0

while(x < 5){
  console.log(x)
  x++
}

// Output: 1,2,3,4

Zrób...pętle while

let x = 0

do{
  console.log(x)
  x++
}while(x < 5)

// Output: 1,2,3,4
 5
Author: ankitkanojia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-08 14:51:36

Podsumowanie:

Kiedy iterację nad tablicą chcemy osiągnąć jeden z następujących celów:]}
  1. Chcemy iterację nad tablicą i utworzyć nową tablicę:

    Array.prototype.map

  2. Chcemy iterację nad tablicą i nie tworzyć nowej tablicy:

    Array.prototype.forEach

    for..of pętla

W JavaScript istnieje wiele sposobów osiągnięcia obu tych celów. Jednak niektóre z nich są bardziej wygodne niż inne. Poniżej znajdziesz kilka powszechnie używanych metod (najwygodniejsza IMO) do wykonania iteracji tablicy w JavaScript.

Tworzenie nowej tablicy: Map

map() jest funkcją znajdującą się na Array.prototype, która może przekształcić każdy element tablicy, a następnie zwraca nową tablicę. map() przyjmuje jako argument funkcję zwrotną i działa w następujący sposób:

let arr = [1, 2, 3, 4, 5];

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

Wywołanie zwrotne, które przekazaliśmy map() jako argument jest wykonywany dla każdego elementu. Następnie zwracana jest tablica, która ma taką samą długość jak oryginalna tablica. W tej nowej tablicy element jest przekształcany przez funkcję wywołania zwrotnego przekazaną jako argument do map().

Różnica pomiędzy map a innym mechanizmem pętli, takim jak forEach i for..of jest taka, żemap zwraca nową tablicę i pozostawia starą tablicę nienaruszoną (chyba że jawnie manipulujesz nią za pomocą myśli splice).

Uwaga że wywołanie zwrotne funkcji map dostarcza Numer indeksu bieżącej iteracji jako drugi argument. Co więcej, czy trzeci argument dostarcza tablicy, na której map został wywołany? Czasami te właściwości mogą być bardzo przydatne.

Pętla za pomocą forEach

forEach jest funkcją znajdującą się na Array.prototype, która przyjmuje funkcję zwrotną jako argument. Następnie wykonuje tę funkcję zwrotną dla każdego elementu w tablicy. W przeciwieństwie do funkcji map(), forEach funkcja nie zwraca nic (undefined). Na przykład:

let arr = [1, 2, 3, 4, 5];

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

Podobnie jak funkcja map, wywołanie zwrotne forEach dostarcza Numer indeksu bieżącej iteracji jako drugi argument. Czy trzeci argument dostarcza tablicy, na której forEach został wywołany?

Pętla przez elementy za pomocą for..of

Pętla for..of przenika przez każdy element tablicy (lub inny obiekt iteracyjny). Działa w następujących sposób:

let arr = [1, 2, 3, 4, 5];

for(let element of arr) {
  console.log(element * 2);
}

W powyższym przykładzie, element oznacza element tablicy, a {[31] } jest tablicą, którą chcemy zapętlić. Zauważ, że nazwa element jest dowolna i mogliśmy wybrać dowolną inną nazwę, taką jak ' el ' lub coś bardziej deklaratywnego, gdy ma to zastosowanie.

Nie myl pętli for..in z pętlą for..of. for..in będzie w pętli przez wszystkie właściwości tablicy, podczas gdy pętla for..of będzie w pętli tylko przez elementy tablicy. Na przykład:

let arr = [1, 2, 3, 4, 5];

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}
 5
Author: Willem van der Veen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-28 18:11:58