For-each nad tablicą w 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.
28 answers
TL; DR
- nie używaj
for-in
chyba, że używasz go z zabezpieczeniami lub przynajmniej wiesz, dlaczego może cię ugryźć. -
Twoje najlepsze zakłady to zazwyczaj
Ale jest wiele więcej do zbadania, 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żna używać ES2015 opcje teraz , nawet w 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"):
- użycie
forEach
i pokrewne (ES5+) - użyj prostej
for
pętli - użycie
for-in
poprawnie
W tym celu należy użyć iteratora (ES2015+).]}
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 funkcję wywołania zwrotnego 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 (w przypadku, gdy twoja funkcja jeszcze nie ma to poręczne).
O ile nie obsługujesz przestarzałych przeglądarek, takich jak IE8 (który netapps pokazuje nieco ponad 4% udziału w rynku od tego napisania we wrześniu 2016), możesz z przyjemnością 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, jako są one dostarczane jako argumenty do funkcji iteracji i tak ładnie ograniczone 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
(przestaje zapętlać za pierwszym razem wywołanie zwrotne zwracafalse
lub coś false) -
some
(po pierwsze, gdy wywołanie zwrotne powracatrue
lub coś prawdziwego) -
filter
(tworzy nową tablicę zawierającą elementy, w których funkcja filtra zwracatrue
i pomija te, w których zwracafalse
) -
map
(tworzy nową tablicę z wartości zwracanych przez wywołanie zwrotne) -
reduce
(buduje wartość poprzez wielokrotne wywołanie wywołania zwrotnego, przekazywanie poprzednich wartości; szczegółowe informacje można znaleźć w specyfikacji; przydatne do sumowania zawartości tablicy i wielu innych rzeczy) -
reduceRight
(podobnie jakreduce
, ale działa w kolejności malejącej, a nie rosnącej)
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 i jest w kodzie wrażliwym na wydajność( mało prawdopodobne), nieco bardziej skomplikowana wersja 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); // Would cause "ReferenceError: index is not defined"
//console.log(value); // Would cause "ReferenceError: value is not defined"
I kiedy to zrobisz, nie tylko value
, ale także index
jest odtwarzane dla każdej iteracji pętli, co oznacza zamknięcia utworzone w ciele pętli zachowują odniesienie do index
(i value
) utworzonych dla tej konkretnej iteracji:
let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
divs[index].addEventListener('click', e => {
alert("Index is: " + index);
});
}
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
Ludzie każą ci używać for-in
, ale to nie jest to, co {21]} jest dla. for-in
pętle poprzez 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 to nie definiuje, że for-in
będzie postępować zgodnie z tą kolejnością. (Szczegóły w tej drugiej odpowiedzi .)
Mimo to, to może być przydatne, szczególnie na sparse tablice, jeśli używasz odpowiednich zabezpieczeń:
// `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 are explained
/^0$|^[1-9]\d*$/.test(key) && // and then hidden
key <= 4294967294 // away below
) {
console.log(a[key]);
}
}
Zwróć uwagę na dwie kontrole:
-
Obiekt posiada własną właściwość o tej nazwie (nie dziedziczy po swoim prototypie), oraz
Że klucz jest ciągiem liczbowym base - 10 w postaci zwykłego ciągu znaków, a jego wartość 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 racja.)
Jest to malutki narzut na iterację pętli na większości tablic, ale jeśli masz rzadką tablicę, może to być bardziej efektywny sposób pętli, ponieważ pętle są tylko dla wpisów, które rzeczywiście istnieją. Np. dla powyższej tablicy pętlujemy łącznie trzy razy (dla kluczy "0"
, "10"
, i "10000"
- pamiętaj, że to sznurki), a nie 10 001 razy.
Teraz nie będziesz chciał tego pisać za każdym razem, więc możesz umieścić to w swoim zestaw narzędzi:
function arrayHasOwnIndex(array, prop) {
return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2
}
I wtedy użylibyśmy tego tak:
for (key in a) {
if (arrayHasOwnIndex(a, key)) {
console.log(a[key]);
}
}
Jeśli nie chcesz, aby twój test był wystarczająco dobry dla większości przypadków, możesz go użyć, ale mimo, że jest blisko, nie jest do końca poprawny.]}
for (key in a) {
// "Good enough" for most cases
if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
console.log(a[key]);
}
}
4. W tym celu należy użyć iteratora.]}
ES2015 dodaje Iteratory do JavaScript. Najprostszym sposobem użycia iteratorów jest nowa Instrukcja for-of
. Wygląda na to, że to:
var val;
var a = ["a", "b", "c"];
for (val of a) {
console.log(val);
}
Wyjście:
a b c
Pod pokrywą, który otrzymuje 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 indeksy.
5. Użycie iteratora jawnie (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:
var a = ["a", "b", "c"];
var it = a.values();
var 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
, mówiącą nam, czy jest zrobione, 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
.)
-
values()
: to jest ten, którego użyłem powyżej. Zwraca iterator, gdzie każdyvalue
jest wpisem tablicy dla tej iteracji ("a"
,"b"
, i"c"
w przykładzie wcześniejszym). -
keys()
: zwraca iterator, w którym każdyvalue
jest kluczem do tej iteracji(więc dla naszegoa
powyżej, to będzie"0"
, następnie"1"
, następnie"2"
). -
entries()
: zwraca iterator, gdzie każdyvalue
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 możemy przejrzeć ich zawartość?
Użyj dowolnej z powyższych opcji dla tablic
[139]}przynajmniej niektóre, a być może Większość lub nawet wszystkie, podejścia do tablicy powyżej często stosują się równie dobrze do obiektów podobnych do tablicy: {142]}-
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 poprzezFunction#call
lubFunction#apply
. (Patrz zastrzeżenie dla obiektów hosta na końcu tej odpowiedzi, ale to rzadki problem.)Załóżmy, że chcesz użyć
forEach
naNode
'SchildNodes
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` });
-
Użyj prostej pętli
for
Oczywiście, prosta
for
pętla ma zastosowanie do tablicy obiektów. -
Użycie
for-in
prawidłowofor-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. -
Use
for-of
(use an iterator implicite) (ES2015+)for-of
użyje iteratora dostarczonego przez obiekt( jeśli istnieje); będziemy musieli zobaczyć, jak to działa z różnymi obiektami typu array, szczególnie te, które są dostarczane przez gospodarzy. Na przykład SpecyfikacjaNodeList
zquerySelectorAll
została zaktualizowana, aby wspierać iterację. Spec dlaHTMLCollection
zgetElementsByTagName
nie było. -
Jawnie używaj iteratora (ES2015+)
Patrz #4, musimy zobaczyć, jak Iteratory się rozegrają.
Tworzenie prawdziwej tablicy
Innym razem możesz chcieć przekonwertować obiekt podobny do tablicy na tablicę rzeczywistą. To zaskakujące. łatwe:
-
Użyj
slice
metoda tablicMożemy użyć metody
slice
tablic, która podobnie jak inne metody wymienione powyżej jest "celowo ogólna" i dlatego może być używana z obiektami podobnymi do tablic, 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 Uwaga że to się nie powiedzie w IE8 i wcześniejszych, co nie pozwala używać obiektów dostarczanych przez host jako
this
W ten sposób. -
Użyj składni spread (
Możliwe jest również użycie składni spreadowej ES2015 z silnikami JavaScript, które obsługują tę funkcję:...
)var trueArray = [...iterableObject];
Więc na przykład, jeśli chcemy przekonwertować
NodeList
do tablicy true, ze składnią spread staje się to całkiem zwięzłość:var divs = [...document.querySelectorAll("div")];
-
Użycie
Array.from
(spec) | (MDN)Array.from
(ES2015+, ale łatwo polyfilled) tworzy tablicę z obiektu podobnego do tablicy, opcjonalnie przekazując najpierw wpisy 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 hosta-pod warunkiem obiekty
Jeśli używasz Array.prototype
funkcji z obiektami typu array (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 typu host 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 szczera odpowiedź na abstrakcję [[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, na początku tej sekcji znajduje się kilka akapitów pod dużą tabelą, 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 pobiera 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ć.)
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-16 13:23:53
Edit : 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.
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-10-06 06:11:45
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].
}
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ć zarray.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 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 czytać , niż niektóre z innych dostępnych opcji. Chociaż przegrywa z
forEach()
i zfor ... 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 wiarygodnym wskazaniem 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 jest użyć forEach ()
Ogólnie dla kodu wyższego poziomu, gdzie przejrzystość i bezpieczeństwo są większe obawy, polecam użycie Array::forEach
jako domyślny wzór:
- jest jasne, aby przeczytać.
- oznacza to, że i nie zostanie przesunięty w obrębie bloku (co jest zawsze możliwą niespodzianką ukrywającą się w długich pętlach
for
iwhile
.) - daje masz wolną przestrzeń do 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 do przodu może wskazywać, że przesunięcie może mieć miejsce.
(jeśli dyskusja na temat intencji nie ma dla Ciebie sensu, to Ty i twój kod możecie skorzystaj z wykładu Crockforda na temat styl programowania i twój mózg .)
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 środkową klauzulą (gdzie zwykle widzimy porównanie), a ostatnia klauzula jest pusta (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 to zacząć od
array.length
bez eksplodowania?Ponieważ
i--
uruchamia przed każdą iteracją, na pierwszej iteracji będziemy mieli dostęp do elementu warray.length - 1
, co pozwala uniknąć problemów zArray-out-of-boundsundefined
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ńcowyi--
zmniejszai
, 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 iteracjii--
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 lubią rysować małą strzałkę na odwrocie for
pętla, i koniec z przymrużeniem oka:
for (var i = array.length; i --> 0 ;) {
/ align = "center" bgcolor = "# e0ffe0 " / cesarz chin / / align = center /
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:03:09
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.
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.
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
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
}
);
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
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
.
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 rodzimeforEach
, w tym przypadku, są zarównoo wiele wolniejsze niż normalnafor
pętla....o 90% wolniej . W przypadku dużych zbiorów danych najlepiej trzymać się natywnej pętlifor
. - brak wsparcia break, continue, lub return.
continue
jest rzeczywiście wspierany przez " wypadek", aby kontynuować wangular.forEach
wystarczy umieścićreturn;
w funkcji jakangular.forEach(array, function(item) { if (someConditionIsTrue) return; });
, co spowoduje, że kontynuuj z funkcji dla tej iteracji. Wynika to również z faktu, że natywnyforEach
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.
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
Ł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ż
-
Dokumentacja dla native
Array.prototype.forEach()
. - W for_each...in (MDN) wyjaśnia się, że
for each (variable in object)
jest przestarzały jako część ECMA-357 (EAX ) standard. -
dla...z (MDN) opisuje kolejny sposób iteracji używając
for (variable of object)
jako części propozycji Harmony (ECMAScript 6).
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
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
//!!!
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
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
Od ES6:
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).
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-10-20 15:21:43
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];
...
}
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.
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ęstsze. 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, uruchomi co najmniej jeden CZAS
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 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.
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-11-27 12:29:50
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
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
ECMAScript5 (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 the #" + (index+1) + " in 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 elemencie currenct i wynik 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 tego, ż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]
Mam nadzieję, że to się przyda.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-06-30 17:36:57
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że być "nie" zoptymalizowany, aby działał szybciej niż oryginalna.
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-11-19 16:27:44
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];
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
Najbardziej zbliżonym sposobem do twojego pomysłu byłoby użycie Array.forEach()
, które akceptuje funkcję clojure, 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ż mutates
każdy element i zwraca go w następujący sposób:
var myArray = [1, 2, 3];
myArray = myArray.map(
(item) => {
return item + 1;
}
);
console.log(myArray); // [2, 3, 4]
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-11-09 15:31:44
Składnia lambda zwykle nie działa w IE 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);
});
If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters
$("#ul>li").each(function(**index,value**){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
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-08-16 08:09:53
var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
console.log("Index" + index);
console.log("Element" + item);
})
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-03-15 22:48:33
Możesz wywołać forEach tak:
let Array = [1,3,2];
theArray.forEach((element)=>{
// use the element of the array
console.log(element)
}
Element będzie miał wartość każdego indeksu od 0 do długości tablicy.
Wyjście:
1
3
2
Wyjaśnienie:
ForEach jest w klasie prototypów. można to również nazwać theArray.prototyp.forEach(...);
Prototyp: https://hackernoon.com/prototypes-in-javascript-5bba2990e04b
Możesz również zmieniać tablicę tak:
for(let i=0;i<theArray.length;i++){
console.log(i); //i will have the value of each index
}
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-17 12:30:51
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);
}
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-05-30 09:05:30
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ą.
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życiefor..in
W takim przypadku, ponieważ zamiast wartości działa z kluczami.
Możesz przeczytać więcej o iteration protocol
tutaj .
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
Podsumowanie:
Podczas iteracji tablicy często możemy chcieć osiągnąć jeden z następujących celów:]}
-
Chcemy iterację nad tablicą i utworzyć nową tablicę:
Array.prototype.map
-
Chcemy iterację nad tablicą i nie tworzyć nowej tablicy:
Array.prototype.forEach
for..of
pętla
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 pętla for..of
jest taka, że map
zwraca jako nową tablicę i pozostawia starą tablicę nienaruszoną (chyba że explicity manipuluje nią myślami w stylu splice
).
Zobacz też że wywołanie zwrotne funkcji map
dostarcza jako drugi argument Numer indeksu bieżącej iteracji. Ponadto trzeci argument podaje tablicę, na której wywołano map
. 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 jako drugi argument Numer indeksu bieżącej iteracji. Trzeci argument podaje również tablicę, na której wywołano forEach
.
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 i {[31] } jest tablicą, którą chcemy zapętlić. Nie, że nazwa {[30] } jest arbitralna i moglibyś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);
}
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-09-08 10:11:23
function printList(callback) {
// do your printList work
console.log('printList is done');
callback();
}
function updateDB(callback) {
// do your updateDB work
console.log('updateDB is done');
callback()
}
function getDistanceWithLatLong(callback) {
// do your getDistanceWithLatLong work
console.log('getDistanceWithLatLong is done');
callback();
}
function runSearchInOrder(callback) {
getDistanceWithLatLong(function() {
updateDB(function() {
printList(callback);
});
});
}
runSearchInOrder(function(){console.log('finished')});
Getdistancewithlong is done updateDB jest zrobione printList is done finished
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-10-01 10:18:28