Pytanie Przeprowadź pętlę przez tablicę w JavaScript


W Javie możesz użyć for Pętla do przechodzenia przez obiekty w tablicy w następujący sposób:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

Czy możesz zrobić to samo w JavaScript?


2421
2018-06-10 00:04


pochodzenie


Ok, więc jestem nieco zdezorientowany, czy można używać ulepszonej pętli for podczas uzyskiwania dostępu do obiektów? I użyć sekwencyjnego do wypełnienia? Czy to jest poprawne? - Mark Szymanski
nie, to naprawdę proste, obiekty tablicy mają indeksy numeryczne, więc chcesz powtarzać nad tymi indeksami w kolejności numerycznej pętla sekwencyjna zapewnia, że ulepszony  for-in pętla wylicza właściwości obiektu, bez określonej kolejności, a także wylicza właściwości dziedziczone ... dla iterowanie ponad tablice sekwencyjne pętle są zawsze zalecane ... - CMS
związane z - stackoverflow.com/questions/5349425/... - jondavidjohn
związane z - stackoverflow.com/q/6208964/31671 - alex
jsben.ch/#/Q9oD5 <= Tutaj benchmark wielu rozwiązań do przechodzenia przez tablice - EscapeNetscape


Odpowiedzi:


Użyj sekwencyjnego for pętla:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    alert(myStringArray[i]);
    //Do something
}

@zipcodeman sugeruje użycie for...in oświadczenie, ale do powtarzania tablic for-in należy unikać, to oświadczenie ma na celu wyliczać właściwości obiektu.

Nie powinno się go używać do obiektów tablicowych, ponieważ:

  • Kolejność iteracji nie jest gwarantowana, indeksy tablic nie mogą być odwiedzane w kolejności numerycznej.
  • Dziedziczone właściwości są również wyliczane.

Drugą kwestią jest to, że może dać ci wiele problemów, na przykład, jeśli przedłużysz Array.prototype Aby obiekt zawierał tam metodę, ta właściwość również zostanie wyliczona.

Na przykład:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
  alert(array[i]);
}

Powyższy kod wyświetli ostrzeżenie "a", "b", "c" i "foo!".

Jest to szczególnie problematyczne, jeśli używasz biblioteki, która opiera się głównie na ulepszeniach natywnych prototypów (takich jak na przykład MooTools).

The for-in oświadczenie, jak już wcześniej powiedziałem, jest wyliczać właściwości obiektu, na przykład:

var obj = {
  "a": 1,
  "b": 2,
  "c": 3
};

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) { 
  // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
    alert("prop: " + prop + " value: " + obj[prop])
  }
}

W powyższym przykładzie hasOwnProperty metoda umożliwia wyliczanie tylko własne właściwości, to wszystko, tylko właściwości, które fizycznie obiekt ma, żadnych dziedziczonych właściwości.

Polecam Ci przeczytać następujący artykuł:


3060
2018-06-10 00:07



Dlaczego głosowanie w dół? for...inpowinno być unikany dla obiektów typu Array! - CMS
To jest powód (sam CMS) stackoverflow.com/questions/1885317/... - OscarRyz
@DoubleGras, myślę, że jest to opinia, której nie podzielają wszyscy. Widzieć: stackoverflow.com/questions/5752906/... lub groups.google.com/forum/?fromgroups#!topic/jsmentors/... - Matthijs Wessels
@StijndeWitt Nie, ponieważ to się zepsuje, jeśli masz jakiekolwiek "falsey" wartości w twojej tablicy: false, undefined, 0, "", NaN. - Phrogz
jsperf.com/caching-array-length/4  Oto test, aby sprawdzić, czy warto buforować długość tablicy w pętli JavaScript - Enrico


Tak, ale tylko jeśli twoja implementacja obejmuje for...of funkcja wprowadzona w ECMAScript 2015 (wydanie "Harmony").

Działa to tak:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

Albo jeszcze lepiej, ponieważ ECMAScript 2015 dostarcza również zmiennych blokowych przez let i const:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

Wielu programistów JavaScript nadal pracuje w środowisku, które jeszcze nie istnieje - zwłaszcza jeśli pisze się kod do uruchamiania w przeglądarkach internetowych, gdzie twórcy witryny często nie mogą być pewni jakiej przeglądarki / wersji będą używać swoich klientów.

Jeśli możesz założyć, że interpreter JavaScript jest zgodny z poprzedni wydanie specyfikacji ECMAScript (która wyklucza na przykład wersje Internet Explorera przed 9), możesz wtedy użyć forEach metoda iteratora zamiast pętli. W takim przypadku przekazujesz funkcję, która ma zostać wywołana dla każdego elementu w tablicy:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

Ale jeśli nawet to jest zbyt wiele do przyjęcia, a ty chcesz czegoś, co działa wszystko wersje JavaScript, musisz użyć jawnej pętli liczącej. Najbezpieczniejsza wersja, która poprawnie obsługuje rzadkie tablice, jest podobna do tej:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Przypisywanie wartości długości do zmiennej lokalnej (w przeciwieństwie do pełnej wartości myStringArray.length wyrażenie w warstwie pętli) może spowodować znaczącą różnicę w wydajności, ponieważ pomija wyszukiwanie właściwości za każdym razem; używając Rhino na moim komputerze, przyspieszenie wynosi 43%.

Często będziesz widział buforowanie długości wykonane w klauzuli inicjalizacji pętli, jak poniżej:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

The for...in składnia wspomniana przez innych jest dla pętli nad właściwościami obiektu; ponieważ tablica w JavaScript jest po prostu obiektem o numerycznych nazwach właściwości (i jest automatycznie aktualizowana lengthwłaściwość), możesz teoretycznie zapętlić z nią Array. Problem polega jednak na tym, że nie ogranicza się on do liczbowych wartości właściwości (pamiętajmy, że nawet metody są w rzeczywistości tylko właściwościami, których wartością jest zamknięcie), ani też nie są iteracyjne nad liczbami w porządku numerycznym. Dlatego też for...in składnia powinna nie służy do przechodzenia przez tablice.


871
2018-04-16 02:03



Należy zauważyć, że niektórzy tłumacze ustni (np. V8) automatycznie buforują długość tablicy gdyby kod jest wywoływany wystarczająco długo i wykrywa, że ​​długość nie jest modyfikowana przez pętlę. Podczas buforowania długość jest nadal dobra, może nie zapewnić zwiększenia prędkości, gdy kod jest wywoływany wystarczająco dużo razy, aby rzeczywiście coś zmienić. - Phrogz
@ Mark-reed Czy mógłbyś wyjaśnić, dlaczego użyłeś? i in myStringArray w twoim przykładzie? Jak to może być fałszem? - Denis V
@DenisV: false. a=[1,2,3,4]; delete a[2]; for (j in a) { console.log(j); }  Wyjścia 0, 1, 3 i 4. a.length jest wciąż 5. - Mark Reed
Nie sugeruję for j in a. Demonstruję to in Sprawdzanie nie jest zbyteczne, jak twierdziłaś, przez pokazanie wszystkich indeksów i pokazanie, że jest między 0 a length-1 to nie jest. Mogłem też wydrukować 2 in a, który jest rzeczywiście falsepomimo tego, że powiedziałeś, że to niemożliwe. - Mark Reed
@GrijeshChauhan - poprawne. Na przykład IE do wersji 8 go nie obsługuje. Widzieć to pytanie. - Mark Reed


Możesz użyć map, która jest funkcjonalną techniką programowania, która jest również dostępna w innych językach, takich jak Pyton i Haskell.

[1,2,3,4].map( function(item) {
     alert(item);
})

Ogólna składnia to:

array.map(func)

Ogólnie func wziąłby jeden parametr, który jest elementem tablicy. Ale w przypadku JavaScriptu może zająć drugi parametr, którym jest indeks elementu, oraz trzeci parametr, którym jest sama tablica.

Zwracana wartość array.map to kolejna tablica, dzięki czemu możesz jej użyć w następujący sposób:

var x = [1,2,3,4].map( function(item) {return item * 10;});

A teraz x jest [10,20,30,40].

Nie musisz wpisywać funkcji inline. Może to być osobna funkcja.

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

które będą w pewnym sensie równoważne:

 for (item in my_list) {item_processor(item);}

Tylko że nie dostaniesz new_list.


392
2018-06-10 00:09



Nie, ale może być mocniejszy. Sprawdź to: joelonsoftware.com/items/2006/08/01.html - hasen
Ten konkretny przykład jest prawdopodobnie lepiej zaimplementowany przy użyciu Array.forEach. map służy do generowania nowej tablicy. - harto
@hasen, the Array.prototype.map Metoda jest częścią standardu ECMAScript 5th Edition, nie jest jeszcze dostępna we wszystkich implementacjach (np. jej braków IE), również dla iterowanie na tablicy myślę, że Array.prototype.forEach metoda jest więcej semantycznie popraw ... proszę również nie sugerować oświadczenia na wejście, zobacz moją odpowiedź po więcej szczegółów :) - CMS
Różnica pomiędzy forEach i map jest to, że ten pierwszy nie zwraca wyników iteracji. map (czasami a.k.a. collect, ale bardzo różni się od apply) jest wyraźnie przekształceniem każdego elementu tablicy w odpowiedni wynik; to 1-do-1 mapowanie, stąd nazwa. Jest to część całej rodziny operacji, które obejmują reduce (który daje pojedynczy wynik z całej tablicy) i filter (który tworzy podzbiór oryginalnej tablicy) i tak dalej. Natomiast forEach po prostu robi coś z każdym elementem, semantyka nieokreślona. - Mark Reed
Zgłaszanie, ponieważ jeśli faktycznie nie mapujesz czegoś, użycie [] .map jest mylące. [] .forEach ma sens semantyczny i przekazuje te same trzy argumenty do funkcji. - gengkev


W JavaScript nie zaleca się przechodzenia przez Array z pętlą for-in, ale lepiej jest użyć pętli for, takich jak:

for(var i=0, len=myArray.length; i < len; i++){}

Jest również zoptymalizowany ("buforowanie" długości tablicy). Jeśli chcesz dowiedzieć się więcej, przeczytaj mój post na ten temat.


102
2017-12-07 07:24



myArray.forEach (function (obj) {}); jest nadal najlepszy - Jan Sverre
niewielka poprawa: możesz użyć ++i zamiast i++ - roberkules
++i to oldschoolowa optymalizacja, którą kompilatory współczesne robią dla Ciebie w pętli for od dawna :) stackoverflow.com/a/1547433/1033348 - ngryman
@Jannis .forEach ma kilka rzeczy przeciwko niemu. 1) nie macierzysty 2) Wymaga nowego kontekstu wykonania dla KAŻDEGO indeksu, który jest raczej drogi i wydaje się przesadny (patrz dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts) - Jose
Musisz uważać, używając tej pętli. Zacząłem go używać i miałem trudny do zlokalizowania błąd z powodu jednego błędu, który popełniłem. Jeśli zagniedziesz dwie pętle w ten sposób: jsfiddle.net/KQwmL/1. Musisz uważać, aby nazwać var ​​len inaczej w dwóch pętlach, w przeciwnym razie druga pętla zastąpi pierwsze len. - Rui Marques


for (var s of myStringArray) {

(Bezpośrednio odpowiadając na twoje pytanie: teraz możesz!)

Większość innych odpowiedzi jest słuszna, ale nie wspominają (na podstawie tego pisania), że Skrypt ECMA 6 2015 wprowadza nowy mechanizm wykonywania iteracji, for..of pętla.

Ta nowa składnia jest najbardziej eleganckim sposobem na iterowanie tablicy w javascript (o ile nie potrzebujesz indeksu iteracyjnego), ale nie jest jeszcze szeroko obsługiwana przez przeglądarki.

Obecnie działa z przeglądarką Firefox 13+, Chrome 37+ i nie współpracuje natywnie z innymi przeglądarkami (zobacz poniżej zgodność z przeglądarką). Na szczęście mamy kompilatory JS (takie jak Babel), które pozwalają nam dziś korzystać z funkcji następnej generacji.

Działa również na węźle (testowałem go w wersji 0.12.0).

Iterowanie tablicy

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

Iterowanie tablicy obiektów

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var member of band){
  console.log(member.firstName + ' ' + member.lastName); 
}

Iteracja generatora:

(przykład wyodrębniony z https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)

function* fibonacci() { // a generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Tabela kompatybilności: http://kangax.github.io/es5-compat-table/es6/#For..of pętli

Spec:  http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}


92
2017-08-11 15:54



Jeśli używasz ES6, sugerowałbym const s zamiast var s - joeytwiddle


Opera, Safari, Firefox i Chrome mają teraz wspólny zestaw ulepszonych metod Array do optymalizacji wielu popularnych pętli.

Możesz nie potrzebować ich wszystkich, ale mogą być one bardzo przydatne, lub jeśli każda przeglądarka je obsługuje.

Mozilla Labs opublikowała algorytmy, które oni i WebKit oba używają, dzięki czemu można je dodać samodzielnie.

filtr zwraca tablicę elementów, które spełniają pewne warunki lub test.

każdy zwraca wartość true, jeśli każdy element tablicy przejdzie test.

trochę zwraca wartość true, jeśli zda test.

dla każdego uruchamia funkcję na każdym elemencie tablicy i nie zwraca niczego.

mapa jest jak dla opcji Any, ale zwraca tablicę wyników operacji dla każdego elementu.

Wszystkie te metody przyjmują funkcję dla ich pierwszego argumentu i mają opcjonalny drugi argument, który jest obiektem, którego zakres chcesz nałożyć na elementy tablicy podczas ich przechodzenia przez funkcję.

Zignoruj ​​go, dopóki go nie potrzebujesz.

indeks i lastIndexOf znajdź odpowiednią pozycję pierwszego lub ostatniego elementu, który dokładnie odpowiada jego argumentowi.

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();

81
2018-06-10 02:43



Dodatek: IE obsługuje forEach od wersji 9, zobacz forEach Metoda MSDN - rwitzel


Użyj pętli while ...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

logi: "jeden", "dwa", "trzy"

I w odwrotnej kolejności, jeszcze bardziej wydajna pętla

var items = ['one','two','three'], i = items.length;
while(i--){
    console.log(items[i]);
}

logi: "trzy", "dwa", "jeden"

Lub klasyczny for pętla

var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

logi: "jeden", "dwa", "trzy"

Odniesienie: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


62
2018-01-05 09:15



Pierwszy przykład składni "while" nie zadziała, jeśli którykolwiek z elementów tablicy jest fałszywy. - Chris Cooper
... i ta pętla while jest równoważna: for (var i = 0, item; item = items [i]; i ++), która eliminuje potrzebę wcześniejszego zadeklarowania zmiennych indeksu i pozycji ... - Stijn de Witt
@StijndeWitt Ale w tym przypadku obowiązuje: jeśli wartość jest falsy, to nie zadziała... - yckart
Podczas iterowania nad kolekcją należy zadbać o optymalizację. Może to wpłynąć na wydajność strony. - Zaheer Ahmed


Wprowadzenie

Od czasu mojej nauki w szkole programowałem w Javie, JavaScript, Pascal, ABAP, PHP, Progress 4GL, C / C ++ i prawdopodobnie kilka innych języków, o których teraz nie myślę.

Chociaż wszystkie mają swoje własne językowe cechy, każdy z tych języków ma wiele wspólnych podstawowych pojęć. Takie pojęcia obejmują procedury / funkcje, IF-sprawozdania, FOR-loopy, i WHILE-Oops.


Tradycyjny for-pętla

Tradycyjny for pętla składa się z trzech elementów:

  1. Inicjalizacja: wykonywane przed pierwszym wyświetleniem bloku look
  2. Warunek: sprawdza warunek za każdym razem przed wykonaniem bloku pętli i zamyka pętlę, jeśli jest false
  3. Po refleksji: wykonywane za każdym razem po wykonaniu bloku pętli

Te trzy składniki są oddzielone od siebie przez a ; symbol. Treść każdego z tych trzech składników jest opcjonalna, co oznacza, że ​​poniższe są najbardziej minimalne for możliwa pętla:

for (;;) {
    // Do stuff
}

Oczywiście, będziesz musiał dołączyć if(condition === true) { break; }  lub if(condition === true) { return; } gdzieś w tym for-laop, żeby przestał działać.

Zwykle inicjalizacja służy do zadeklarowania indeksu, warunek jest używany do porównywania tego indeksu z wartością minimalną lub maksymalną, a do zwiększenia indeksu używana jest dodatkowa myśl:

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

Korzystanie z tradycyjnych for pętla do przechodzenia przez tablicę

Tradycyjny sposób przechodzenia przez macierz to:

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

Lub, jeśli wolisz pętlę wstecz, wykonaj następujące czynności:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

Istnieje jednak wiele możliwych wariantów, na przykład ta:

for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
    console.log(value);
}

... albo ten ...

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

... albo ten:

var key = 0, value;
for (; value = myArray[key++];){
    console.log(value);
}

To, które działa najlepiej, jest w dużej mierze kwestią zarówno osobistego gustu, jak i konkretnego zastosowania, które stosujesz.

Pamiętaj, że każda z tych odmian jest obsługiwana przez wszystkie przeglądarki, w tym bardzo stare!


ZA while pętla

Jedna alternatywa dla a for pętla to whilepętla. Aby przechwycić tablicę, możesz to zrobić:

var key = 0;
while(value = myArray[key++]){
    console.log(value);
}

Podobnie jak tradycyjny for pętle, while pętle są obsługiwane przez nawet najstarsze przeglądarki.

Pamiętaj też, że każdą pętlę while można przepisać jako for pętla. Na przykład while pętla powyżej zachowuje się dokładnie tak samo jak ta for-pętla:

for(var key = 0; value = myArray[key++];){
    console.log(value);
}

For...in i for...of

W JavaScript możesz również:

for (i in myArray) {
    console.log(myArray[i]);
}

Powinno się go jednak używać ostrożnie, ponieważ nie zachowuje się tak samo jak tradycyjne for pętli we wszystkich przypadkach i istnieją potencjalne skutki uboczne, które należy wziąć pod uwagę. Widzieć Dlaczego używanie "for ... in" z iteracją tablicy jest złym pomysłem? po więcej szczegółów.

Jako alternatywa dla for...in, teraz jest również dla for...of. Poniższy przykład pokazuje różnicę między for...of pętla i for...in pętla:

var myArray = [3, 5, 7];
myArray.foo = "hello";

for (var i in myArray) {
  console.log(i); // logs 0, 1, 2, "foo"
}

for (var i of myArray) {
  console.log(i); // logs 3, 5, 7
}

Dodatkowo musisz wziąć pod uwagę, że żadna wersja Internet Explorera nie obsługuje for...of (Krawędź 12+ robi) i to for...in wymaga przynajmniej Internet Explorera 10.


Array.prototype.forEach()

Alternatywa dla for-moopy są Array.prototype.forEach(), który używa następującej składni:

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

Array.prototype.forEach() jest obsługiwany przez wszystkie nowoczesne przeglądarki, a także Internet Explorer 9 i nowsze.


Biblioteki

Wreszcie, wiele bibliotek narzędziowych ma swoje własne foreach zmiana. AFAIK, trzy najbardziej popularne z nich to:

jQuery.each(), w jQuery:

$.each(myArray, function(key, value) {
    console.log(value);
});

_.each(), w Underscore.js:

_.each(myArray, function(value, key, myArray) {
    console.log(value);
});

_.forEach(), w Lodash.js:

_.forEach(myArray, function(value, key) {
    console.log(value);
});

48
2018-02-29 18:56





Jeśli chcesz krótki sposób napisania szybkiej pętli i możesz iterować na odwrót:

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

Ma to zaletę buforowania długości (podobną do for (var i=0, len=myArray.length; i<len; ++i) i w przeciwieństwie do for (var i=0; i<myArray.length; ++i)), chociaż jest mniej znaków do wpisania.

Są nawet czasami, kiedy powinieneś iterować na odwrót, na przykład podczas iteracji po live NodeList gdzie planujesz usuwanie elementów z DOM podczas iteracji.


35
2018-06-04 16:26



Dla ludzi, którzy nie dostają tego, co jest genialne: wyrażenie i-- jest najpierw oceniane i pozwala pętli kontynuować, gdy nie jest falsy ... Potem licznik jest zmniejszany. Jak tylko zejdę do zera, wyrwie się z pętli, ponieważ zero jest fałszywą wartością w JavaScript. - Stijn de Witt
falsish? Masz na myśli False. Wszyscy trzymajmy właściwą terminologię, aby uniknąć nieporozumień;) - danwellman
Widziałem termin "fałsz" używany przez ludzi, których uważam za guru. Jeśli jest wystarczająco dobre dla nich, to jest dla mnie wystarczająco dobre. Jestem również rozczarowany, że mój komentarz, który jest rzeczywiście ontopyczny i dodaje wyjaśnienie / wgląd, dostaje 0 przegranych, ale komentarz, który niszczy w pewnym terminie w moim komentarzu, jest 4. Ach, tak, to tylko kwestia priorytetów. - Stijn de Witt
"Buforowanie długości"? Długość jest zapisywana jako liczba całkowita w tablicy, nie jest mierzona za każdym razem, gdy uzyskujesz do niej dostęp. W kopiowaniu wartości długości na inną zmienną nie ma tu żadnej korzyści. - Mouscellaneous
@Mouscellaneous Te dni na pewno nie ma; w poprzednich latach iterowanie tablic JavaScript buforujących długość po stronie JavaScript (zamiast sięgania przez implementację) było wyraźnym przyrostem perf (kiedy mikrooptymalizacja). Na przykład, for (var i=0,len=array.length;i<len;++i) była powszechna, rozsądna pętla do napisania. - Phrogz


Istnieje sposób, aby to zrobić, gdy masz bardzo mało domniemany zakres w swojej pętli i zlikwiduj dodatkowe zmienne.

var i = 0,
     item;

// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){ 
    item; // This is the string at the index.
}

Lub jeśli naprawdę chcesz uzyskać identyfikator i naprawdę klasyczny for pętla:

var i = 0,
    len = myStringArray.length; // cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

Nowoczesne przeglądarki obsługują wszystkie metody iteratora forEach, map, reduce, filter i wiele innych metod na Prototyp tablicy.


26
2018-05-16 22:52



Zauważ, że niektóre interpretery (na przykład V8) automatycznie buforują długość tablicy, jeśli kod jest wywoływany wystarczająco długo i wykrywa, że ​​długość nie jest modyfikowana przez pętlę. - Phrogz
Dzięki za informację @Phrogz to prawda, że ​​istnieje wiele optymalizacji, które może wykonać VM, ale ponieważ starsze przeglądarki tego nie robią, najlepszą metodą byłoby optymalizacja, ponieważ jest tak tania. - Gabriel
@Gabriel: Dlaczego? Podaj rzeczywiste przykłady pokazujące, że buforowanie długości nie jest w rzeczywistości wąskim gardłem wydajności. Postępuję zgodnie z podejściem "przedwczesnej optymalizacji jest podstawą wszelkiego zła". Naprawię tę pętlę, która faktycznie stanowi problem, gdy ją napotkam ... - Stijn de Witt
@StijndeWitt imo to tylko kwestia stylistyczna. Szczerze mówiąc, nie używam już nawet pętli zamiast polegać na podkreśleniu dla rzeczy takich jak _.each, _.map itp., Aby robić te rzeczy. Kiedy pisałem pętle w ten sposób, buforowałem długość głównie po to, aby wszystkie moje deklaracje zmiennych znajdowały się w jednym miejscu, na szczycie mojej funkcji. Podążanie za moją radą w tym zakresie jest nieistotne w stosunku do jakiegokolwiek zastosowania w świecie rzeczywistym. Przedwczesna optymalizacja jest bardzo zła, ale jeśli optymalizacja wynika z decyzji stylistycznych, nie sądzę, by miało to naprawdę znaczenie. - Gabriel
@Gabriel Wierzę, że JavaScript obsługuje już funkcję mapowania na tablicach, nie ma potrzeby wprowadzania dodatkowej biblioteki. - Noz