Widziałem wiele pytań, które sugerują użycie:
for (var i = 0; i < myArray.length; i++){ /* ... */ }
zamiast:
for (var i in myArray){ /* ... */ }
dla tablic z powodu niespójnej iteracji ( patrz tutaj ).
Jednak nie mogę znaleźć niczego, co wydaje się preferować pętlę obiektową:
myArray.forEach(function(item, index){ /* ... */ });
Co wydaje mi się bardziej intuicyjne.
W przypadku mojego obecnego projektu zgodność z IE8 jest ważna i rozważam użycie polyfill Mozilli , jednak nie jestem w 100% pewien, jak to zadziała.
- Czy są jakieś różnice między standardową pętlą for (pierwszy przykład powyżej) a implementacją Array.prototype.forEach w nowoczesnych przeglądarkach?
- Czy jest jakaś różnica między nowoczesnymi implementacjami przeglądarek a implementacją Mozilli, o której mowa powyżej (ze szczególnym uwzględnieniem IE8)?
- Wydajność nie jest tak dużym problemem, tylko spójność z iterowanymi właściwościami.
javascript
arrays
for-loop
internet-explorer-8
iterator
Michael Lewis
źródło
źródło
break
wyjśćforEach
. Ale dużą zaletą jest utworzenie nowego zakresu z funkcją. Z polyfillem nie powinieneś mieć żadnych problemów (przynajmniej ja żadnych nie spotkałem).holes
gdzieundefined
powinien być, i innych uszkodzonych metod, takich jakslice
ihasOwnProperty
wrt do obiektów DOM przypominających tablice. Moje testy ies5 shim
wykazały, że takie podkładki są zgodne ze specyfikacją (nie testowano podkładki MDN).for
pętlisome
.Array.find()
aby wyrwać się z pętli po znalezieniu pierwszego dopasowania.Odpowiedzi:
Najbardziej istotna różnica między
for
pętlą aforEach
metodą polega na tym, że w przypadku tej pierwszej możeszbreak
wyjść z pętli. Możesz symulowaćcontinue
, po prostu wracając z funkcji przekazanej doforEach
, ale nie ma sposobu, aby całkowicie zatrzymać pętlę.Poza tym oba te rozwiązania skutecznie realizują tę samą funkcjonalność. Inna niewielka różnica dotyczy zakresu indeksu (i wszystkich zawierających zmienne) w pętli for, ze względu na zmienne podnoszenie.
// 'i' is scoped to the containing function for (var i = 0; i < arr.length; i++) { ... } // 'i' is scoped to the internal function arr.forEach(function (el, i) { ... });
Jednak
forEach
wydaje mi się, że jest to dużo bardziej wyraziste - reprezentuje zamiar iteracji przez każdy element tablicy i zapewnia odniesienie do elementu, a nie tylko do indeksu. Ogólnie rzecz biorąc, sprowadza się to głównie do osobistego gustu, ale jeśli możesz go użyćforEach
, polecam go.Pomiędzy tymi dwiema wersjami występuje kilka bardziej istotnych różnic, w szczególności dotyczących wydajności. W rzeczywistości prosta pętla for działa znacznie lepiej niż
forEach
metoda, co wykazano w tym teście jsperf .To, czy takie wykonanie jest dla Ciebie konieczne, zależy od Ciebie, aw większości przypadków wolałbym wyrazistość niż szybkość. Ta różnica szybkości jest prawdopodobnie spowodowana niewielkimi różnicami semantycznymi między podstawową pętlą a metodą podczas pracy na rzadkich tablicach, jak wspomniano w tej odpowiedzi .
Jeśli nie potrzebujesz zachowania
forEach
i / lub musisz wcześnie wyrwać się z pętli, możesz użyć Lo-Dash_.each
jako alternatywy, która będzie działać również w różnych przeglądarkach. Jeśli używasz jQuery, zapewnia on również podobny$.each
, po prostu zwróć uwagę na różnice w argumentach przekazywanych do funkcji zwrotnej w każdej wariacji.(Jeśli chodzi o
forEach
polyfill, powinien działać w starszych przeglądarkach bez problemów, jeśli wybierzesz tę trasę.)źródło
each
nie zachowują się w taki sam sposób jak specyfikacja ECMA5forEach
, mają tendencję do traktowania wszystkich tablic jako gęstych (aby uniknąć błędów IE, pod warunkiem, że jest się tego świadomym). W przeciwnym razie może to być „gotcha”. Jako odniesienie github.com/es-shims/es5-shim/issues/190Array.prototype.some
zapętlenie do momentu zwrócenia prawdziwej wartości lub do całkowitego zapętlenia przez tablicę.Array.prototype.every
jest podobny do,Array.prototype.some
ale zatrzymuje się, jeśli zwrócisz fałszywą wartość.Array.prototype.forEach
jakąś niekompatybilną wersją mogłoby potencjalnie zepsuć tak wiele bibliotek, że unikanie tego z tego powodu i tak nie pomogłoby.Możesz użyć swojej niestandardowej funkcji foreach, która będzie działać znacznie lepiej niż Array.forEach
Powinieneś dodać to raz do swojego kodu. To doda nową funkcję do Array.
function foreach(fn) { var arr = this; var len = arr.length; for(var i=0; i<len; ++i) { fn(arr[i], i); } } Object.defineProperty(Array.prototype, 'customForEach', { enumerable: false, value: foreach });
Następnie możesz go używać w dowolnym miejscu, takim jak Array.forEach
[1,2,3].customForEach(function(val, i){ });
Jedyna różnica to 3 razy szybciej. https://jsperf.com/native-arr-foreach-vs-custom-foreach
AKTUALIZACJA: W nowej wersji Chrome wydajność .forEach () została poprawiona. Jednak rozwiązanie to może zapewnić dodatkową wydajność w innych przeglądarkach.
źródło
Wielu programistów (np. Kyle Simpson)
.forEach
sugeruje użycie do wskazania, że tablica będzie miała efekt uboczny i.map
dla czystych funkcji.for
pętle pasują dobrze jako rozwiązanie ogólnego przeznaczenia dla znanej liczby pętli lub dowolnego innego przypadku, który nie pasuje, ponieważ jest łatwiejszy w komunikacji ze względu na szerokie wsparcie w większości języków programowania.na przykład
/* For Loop known number of iterations */ const numberOfSeasons = 4; for (let i = 0; i < numberOfSeasons; i++) { //Do Something } /* Pure transformation */ const arrayToBeUppercased = ['www', 'html', 'js', 'us']; const acronyms = arrayToBeUppercased.map((el) => el.toUpperCase)); /* Impure, side-effects with .forEach */ const acronymsHolder = []; ['www', 'html', 'js', 'us'].forEach((el) => acronymsHolder.push(el.toUpperCase()));
Z punktu widzenia konwencji wydaje się to najlepsze, jednak społeczność nie zdecydowała się na konwencję dotyczącą nowszych
for in
pętli protokołów iteracyjnych . Ogólnie uważam, że dobrym pomysłem jest podążanie za koncepcjami FP, które społeczność JS wydaje się być otwarta na przyjęcie.źródło