Vraag Loop door een array in JavaScript


In Java kunt u een for lus om objecten in een array als volgt te doorlopen:

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

Kun je hetzelfde doen in JavaScript?


2415
2018-06-10 00:04


oorsprong


antwoorden:


Gebruik een reeks for lus:

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

@zipcodeman suggereert het gebruik van de for...in statement, maar voor iterating arrays for-in moet worden vermeden, die verklaring is bedoeld om opsommen objecteigenschappen.

Het zou niet moeten worden gebruikt voor array-achtige objecten, omdat:

  • De volgorde van iteratie is niet gegarandeerd, de array-indexen worden mogelijk niet in numerieke volgorde bezocht.
  • Overgenomen eigenschappen worden ook opgesomd.

Het tweede punt is dat het je een hoop problemen kan geven, bijvoorbeeld als je de Array.prototype object om daar een methode op te nemen, die eigenschap zal ook worden opgesomd.

Bijvoorbeeld:

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

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

De bovenstaande code waarschuwt "a", "b", "c" en "foo!".

Dat is met name een probleem als u een bibliotheek gebruikt die sterk afhankelijk is van native-prototypen-augmentatie (zoals bijvoorbeeld MooTools).

De for-in verklaring zoals ik al eerder zei is er om opsommen objecteigenschappen, bijvoorbeeld:

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])
  }
}

In het bovenstaande voorbeeld de hasOwnProperty methode kunt u alleen opsommen eigen eigenschappen, dat is het, alleen de eigenschappen die het object fysiek heeft, geen overgeërfde eigenschappen.

Ik zou je aanraden om het volgende artikel te lezen:


3050
2018-06-10 00:07



Ja, maar alleen als uw implementatie de for...of functie geïntroduceerd in ECMAScript 2015 (de "Harmony" -versie).

Het werkt als volgt:

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

Of beter nog, omdat ECMAScript 2015 ook block-scoped variabelen biedt via let en const:

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

Veel JavaScript-ontwikkelaars werken nog steeds in een omgeving die er nog niet is, vooral als code wordt geschreven in webbrowsers, waarbij de ontwikkelaars vaak niet zeker weten welke browser / versie hun clients zullen gebruiken.

Als u kunt aannemen dat de JavaScript-interpreter voldoet aan de voorgaand editie van de ECMAScript-specificatie (die bijvoorbeeld versies van Internet Explorer uitsluit voor 9), dan kunt u de forEach iterator-methode in plaats van een lus. In dat geval geeft u een functie door die moet worden aangeroepen voor elk item in de array:

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

Maar als zelfs dat te veel is om aan te nemen, en je wilt iets dat werkt alle versies van JavaScript, dan moet je een expliciete tellus gebruiken. De veiligste versie, die dunne reeksen goed verwerkt, is zoiets als dit:

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

Wijs de lengtewaarde toe aan de lokale variabele (in tegenstelling tot de volledige variabele myStringArray.length expressie in de lusvoorwaarde) kan een significant verschil in prestaties maken, omdat het een eigenschapopzoeking overslaat elke keer door; met Rhino op mijn machine is de snelheid 43%.

In de clausule voor het initialiseren van de lus ziet u vaak dat de lengte in de cache is geplaatst, zoals hieronder:

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

De for...in syntaxis genoemd door anderen is voor het doorlussen van de eigenschappen van een object; omdat een array in JavaScript slechts een object met numerieke eigenschapnamen is (en automatisch wordt bijgewerkt) lengtheigenschap), kunt u er theoretisch een array mee laten lopen. Maar het probleem is dat het zichzelf niet beperkt tot de numerieke eigenschapswaarden (onthoud dat zelfs methoden in feite alleen eigenschappen zijn waarvan de waarde een afsluiting is), en ook niet itereert die in numerieke volgorde. Daarom, de for...in syntaxis zou moeten niet worden gebruikt voor lusvorming door arrays.


868
2018-04-16 02:03



Je kunt gebruiken map, wat een functionele programmeertechniek is die ook in andere talen beschikbaar is, zoals Python en Haskell.

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

De algemene syntaxis is:

array.map(func)

In het algemeen func zou een parameter nemen, wat een item van de array is. Maar in het geval van JavaScript kan het een tweede parameter zijn, die de index van het item is, en een derde parameter die de array zelf is.

De geretourneerde waarde van array.map is een andere array, dus je kunt het op deze manier gebruiken:

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

En nu is x dat [10,20,30,40].

U hoeft de functie niet inline te schrijven. Het zou een afzonderlijke functie kunnen zijn.

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

new_list = my_list.map(item_processor);

wat ongeveer hetzelfde zou zijn als:

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

Behalve dat je de new_list.


391
2018-06-10 00:09



In JavaScript is het niet raadzaam om door een array te lopen met een for-in-lus, maar het is beter om een ​​for-lus te gebruiken, zoals:

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

Het is ook geoptimaliseerd ("caching" van de array-lengte). Als je meer wilt leren, lees mijn bericht over het onderwerp.


102
2017-12-07 07:24



for (var s of myStringArray) {

(Rechtstreeks uw vraag beantwoorden: nu kunt u!)

De meeste andere antwoorden hebben gelijk, maar ze vermelden niet (vanaf dit schrijven) dat ECMA Script 6 2015 brengt een nieuw mechanisme voor het doen van iteratie, de for..of lus.

Deze nieuwe syntaxis is de elegantste manier om een ​​array in JavaScript te herhalen (zo lang je de iteratie-index niet nodig hebt), maar deze wordt nog niet breed ondersteund door de browsers.

Het werkt momenteel met Firefox 13+, Chrome 37+ en het werkt niet standaard met andere browsers (zie browsercompatibiliteit hieronder). Gelukkig hebben we JS-compilers (zoals Babel) waarmee we tegenwoordig functies van de volgende generatie kunnen gebruiken.

Het werkt ook op Node (ik heb het getest op versie 0.12.0).

Een array herhalen

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

Een reeks objecten herhalen

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

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

Iteratie van een generator:

(voorbeeld geëxtraheerd uit 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;
  }
}

Compatibiliteitstabel: http://kangax.github.io/es5-compat-table/es6/#For..of loops

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

}


92
2017-08-11 15:54



Opera, Safari, Firefox en Chrome delen nu allemaal een set verbeterde Array-methoden voor het optimaliseren van veel algemene lussen.

Mogelijk hebt u ze niet allemaal nodig, maar ze kunnen erg nuttig zijn, of het zou zijn als elke browser ze zou ondersteunen.

Mozilla Labs heeft de algoritmen gepubliceerd die zij en WebKit beide gebruiken, zodat u ze zelf kunt toevoegen.

filter geeft een reeks items terug die aan een bepaalde voorwaarde of test voldoen.

elk geeft true als elk arraylid de test heeft doorstaan.

sommige geeft als resultaat true als de test geslaagd is.

forEach voert een functie uit op elk arraylid en retourneert niets.

kaart is als ForElke, maar het retourneert een array van de resultaten van de bewerking voor elk element.

Deze methoden hebben allemaal een functie voor hun eerste argument en hebben een optioneel tweede argument, dat een object is waarvan u het bereik wilt opleggen aan de arrayleden terwijl ze door de functie lopen.

Negeer het totdat je het nodig hebt.

index van en lastIndexOf zoek de juiste positie van het eerste of laatste element dat precies overeenkomt met het argument.

(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



Gebruik de while-lus ...

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

logs: 'één', 'twee', 'drie'

En voor de omgekeerde volgorde, een nog efficiëntere lus

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

logs: 'drie', 'twee', 'een'

Of het klassieke for lus

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

logs: 'één', 'twee', 'drie'

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


62
2018-01-05 09:15



Intro

Sinds mijn tijd op de universiteit, heb ik geprogrammeerd in Java, JavaScript, Pascal, ABAP, PHP, Progress 4GL, C / C ++ en mogelijk enkele andere talen die ik momenteel niet kan bedenken.

Hoewel ze allemaal hun eigen linguïstische eigenaardigheden hebben, delen al deze talen veel van dezelfde basisbegrippen. Dergelijke concepten omvatten procedures / functies, IF-zinnen, FOR-loops, en WHILE-loops.


Een traditionele for-lus

Een traditionele for loop heeft drie componenten:

  1. De initialisatie: uitgevoerd voordat het look-blok de eerste keer werd uitgevoerd
  2. De conditie: controleert elke keer een voorwaarde voordat het lusblok wordt uitgevoerd en verlaat de lus als deze false is
  3. De bijzaak: uitgevoerd elke keer nadat het lusblok is uitgevoerd

Deze drie componenten zijn van elkaar gescheiden door een ; symbool. Inhoud voor elk van deze drie componenten is optioneel, wat betekent dat het volgende het minst minimaal is for loop mogelijk:

for (;;) {
    // Do stuff
}

Natuurlijk moet u een if(condition === true) { break; }  of een if(condition === true) { return; } ergens daarbinnen for-loop om het te laten stoppen met rennen.

Doorgaans wordt de initialisatie echter gebruikt om een ​​index te declareren, de voorwaarde wordt gebruikt om die index te vergelijken met een minimum- of maximumwaarde en de bijzaak wordt gebruikt om de index te verhogen:

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

Een traditioneel gebruiken for lus om door een array te lopen

De traditionele manier om door een array te lopen, is dit:

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

Of, als u liever achteruit loopt, doet u dit:

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

Er zijn echter veel variaties mogelijk, zoals bijvoorbeeld deze:

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

... of deze ...

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

... of deze:

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

Wat het beste werkt, is grotendeels een kwestie van zowel persoonlijke smaak als de specifieke gebruikscase die u implementeert.

Merk op dat elk van deze variaties wordt ondersteund door alle browsers, inclusief heel erg oude!


EEN while lus

Een alternatief voor een for loop is a whilelus. Om door een array te lus te gaan, zou je dit kunnen doen:

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

Zoals traditioneel for loops, while loops worden zelfs door de oudste browsers ondersteund.

Merk ook op dat elke while-lus kan worden herschreven als een for lus. Bijvoorbeeld de while loop hierboven gedraagt ​​zich exact hetzelfde als dit for-lus:

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

For...in en for...of

In JavaScript kunt u dit ook doen:

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

Dit moet echter voorzichtig worden gebruikt, omdat het niet hetzelfde gedrag vertoont als een traditioneel for loop in alle gevallen, en er zijn mogelijke bijwerkingen die moeten worden overwogen. Zien Waarom is het gebruik van "voor ... in" met array-iteratie een slecht idee? voor meer details.

Als een alternatief voor for...in, er is nu ook voor for...of. In het volgende voorbeeld ziet u het verschil tussen een for...of loop en a for...in lus:

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
}

Bovendien moet u overwegen dat geen enkele versie van Internet Explorer ondersteunt for...of (Edge 12+ doet) en dat for...in vereist ten minste Internet Explorer 10.


Array.prototype.forEach()

Een alternatief voor for-loops is Array.prototype.forEach(), die de volgende syntaxis gebruikt:

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

Array.prototype.forEach() wordt ondersteund door alle moderne browsers, evenals Internet Explorer 9 en hoger.


bibliotheken

Ten slotte hebben veel hulpprogramma-bibliotheken ook een eigen bibliotheek foreach variatie. AFAIK, de drie meest populaire zijn deze:

jQuery.each(), in jQuery:

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

_.each(), in Underscore.js:

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

_.forEach(), in Lodash.js:

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

48
2018-02-29 18:56



Als je een beknopte manier wilt om een ​​snelle lus te schrijven en je kunt in omgekeerde volgorde herhalen:

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

Dit heeft het voordeel dat de lengte in de cache wordt opgeslagen (vergelijkbaar met for (var i=0, len=myArray.length; i<len; ++i) en in tegenstelling tot for (var i=0; i<myArray.length; ++i)) terwijl u minder tekens gebruikt om te typen.

Er zijn zelfs enkele keren dat je in omgekeerde volgorde zou moeten itereren, zoals bij het itereren over een live NodeList waar u van plan bent items uit de DOM te verwijderen tijdens iteratie.


35
2018-06-04 16:26