Parcurge un șir în JavaScript


În Java, poți folosi un ciclu for pentru a parcurge obiecte într-un array după cum urmează:

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

Pot să fac la fel în JavaScript?

Răspuns #1

Trei opțiuni principale:

  1. for (var i = 0; i < xs.length; i++) { console.log(xs[i]); }
  2. xs.forEach((x, i) => console.log(x));
  3. for (const x of xs) { console.log(x); }

Exemple detaliate sunt mai jos.


1. Buclă for secvențială:

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

Pro

  • Funcționează în orice mediu
  • Poți folosi instrucțiunile de control al fluxului break și continue

Dezavantaje

  • Prea multă vorbărie
  • Imperativ
  • Ușor de a avea erori de tip off-by-one (uneori numite și eroare de stâlp de gard)

2. Array.prototype.forEach:

Specificația ES5 a introdus o mulțime de metode utile pentru array-uri. Una dintre ele, Array.prototype.forEach, ne-a oferit un mod concis de a parcurge un array:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

Fiind aproape zece ani de la momentul scrierii când specificația ES5 a fost lansată (decembrie 2009), aceasta a fost implementată de aproape toate motoarele moderne din mediile desktop, server și mobile, așa că este sigur să le folosești.

Și cu sintaxa funcțiilor săgeată ES6, este și mai concis:

array.forEach(item => console.log(item));

Funcțiile săgeată sunt, de asemenea, implementate pe scară largă, cu excepția cazului în care intenționați să suportați platforme antice (de exemplu, Internet Explorer 11); de asemenea, sunteți în siguranță să le utilizați.

Avantaje

  • Foarte scurt și concis.
  • Declarativ

Contra

  • Nu se poate folosi break/continue

În mod normal, puteți înlocui necesitatea de a folosi break pentru a ieși din bucle imperative prin filtrarea elementelor array-ului înainte de a le itera, de exemplu:

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

Țineți minte că dacă iterați un array pentru a construi un alt array din el, ar trebui să folosiți map. Am văzut acest anti-pattern de atât de multe ori.

Anti-model:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

Caz de utilizare corectă a map:

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

De asemenea, dacă încerci să reduce (reduci) un array la o valoare, de exemplu, dacă vrei să aduni un array de numere, ar trebui să folosești metoda reduce.

Anti-model:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

Utilizarea corectă a reduce:

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. Instrucțiunea ES6 for-of:

Standardul ES6 introduce conceptul de obiecte iterabile și definește un nou construct pentru parcurgerea datelor, instrucțiunea for...of.

Această afirmație funcționează pentru orice tip de obiect iterabil și, de asemenea, pentru generatoare (orice obiect care are o proprietate \[Symbol.iterator\]).

Obiectele de tip array sunt, prin definiție, iterabile încorporate în ES6, așa că poți folosi această instrucțiune pe ele:

let colors = ['red', 'green', 'blue'];
for (const color of colors){
    console.log(color);
}

Avantaje

  • Poate itera peste o mare varietate de obiecte.
  • Poate folosi declarațiile normale de control al fluxului (break/continue).
  • Util pentru a itera valori asincrone în serie.

Dezavantaje

  • Dacă vizați browsere mai vechi, rezultatul transpus ar putea să vă surprindă.

Nu folosiți for...in

@zipcodeman sugerează utilizarea instrucțiunii for...in, dar pentru iterarea array-urilor for-in ar trebui evitat, acea instrucțiune este menită să enumere proprietățile obiectelor.

Nu ar trebui să fie folosit pentru obiecte de tip array deoarece:

  • Ordinea de iterare nu este garantată; indexurile din tabloul array nu pot fi vizitate în ordine numerică.
  • Proprietățile moștenite sunt, de asemenea, enumerate.

Al doilea punct este că vă poate da multe probleme, de exemplu, dacă extindeți obiectul Array.prototype pentru a include o metodă acolo, acea proprietate va fi de asemenea enumerată.

De exemplu:

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

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

Codul de mai sus va afișa în consolă „a”, „b”, „c” și „foo!”.

Asta poate fi în special o problemă dacă folosești o bibliotecă care se bazează mult pe augmentarea prototipurilor native (cum ar fi MooTools).

Instrucțiunea for-in, așa cum am spus înainte, este acolo pentru a enumera proprietățile obiectelor, de exemplu:

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...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

În exemplul de mai sus, metoda hasOwnProperty îți permite să enumeri doar proprietățile proprii. Atât, doar proprietățile pe care le are fizic obiectul, fără proprietăți moștenite.

Ți-aș recomanda să citești următorul articol:

  • Enumerare VS Iterație

Răspunsul #2

Da, presupunând că implementarea ta include funcționalitatea for...of introdusă în ECMAScript 2015 (lansarea „Harmony”)... ceea ce este o presupunere destul de sigură în zilele noastre.

Funcționează astfel:

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

Sau mai bine, având în vedere că ECMAScript 2015 oferă și variabile cu scop de bloc:

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

(Variabila s este diferită la fiecare iterație, dar poate fi totuși declarată const în interiorul corpului buclei atât timp cât nu este modificată acolo.)

O notă despre tablourile rare (sparse arrays): un tablou în JavaScript s-ar putea să nu stocheze efectiv atâtea elemente câte sunt raportate de length; acest număr este pur și simplu cu unul mai mare decât cel mai mare index la care este stocată o valoare. Dacă tabloul conține mai puține elemente decât indică lungimea sa, se spune că este rar. De exemplu, este perfect legitim să ai un tablou cu elemente doar la indicii 3, 12 și 247; length al unui astfel de tablou este 248, deși stochează efectiv doar 3 valori. Dacă încerci să accesezi un element la orice alt index, tabloul va părea că are valoarea undefined acolo, însă tabloul este totuși diferit de unul care are efectiv valori undefined stocate. Poți vedea această diferență în mai multe moduri, de exemplu în modul în care REPL-ul Node afișează tablourile:

> a              // array with only one item, at index 12
[ <12 empty items>, 1 ]
> a[0]           // appears to have undefined at index 0
undefined
> a[0]=undefined // but if we put an actual undefined there
undefined
> a              // it now looks like this
[ undefined, <11 empty items>, 1 ]

Așadar, atunci când vrei să „parcurgi” un array, ai o întrebare de răspuns: vrei să parcurgi întreaga gamă indicată de lungimea sa și să procesezi undefined pentru orice elemente lipsă, sau vrei să procesezi doar elementele efectiv prezente? Există multe aplicații pentru ambele abordări; totul depinde de ceea ce folosești array-ul.

Dacă iterați peste un array cu for..of, corpul buclei este executat de length ori, iar variabila de control a buclei este setată la undefined pentru orice elemente care nu sunt efectiv prezente în array. În funcție de detaliile codului vostru „faceți ceva cu”, acest comportament poate fi ceea ce doriți, dar dacă nu, ar trebui să folosiți o abordare diferită.

Desigur, unii dezvoltatori nu au de ales decât să folosească oricum o abordare diferită, deoarece dintr-un motiv sau altul vizează o versiune de JavaScript care încă nu suportă for...of.

Atâta timp cât implementarea ta de JavaScript este conformă cu ediția anterioară a specificației ECMAScript (ceea ce exclude, de exemplu, versiunile Internet Explorer înainte de 9), atunci poți folosi metoda iterator Array#forEach în locul unei bucle. În acest caz, transmiți o funcție care va fi apelată pentru fiecare element din array:

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

Desigur, poți folosi o funcție săgeată dacă implementarea ta suportă ES6+:

myStringArray.forEach( s => { 
     // ... do something with s ...
} );

Spre deosebire de for...of, .forEach apelează funcția doar pentru elementele care sunt efectiv prezente în array. Dacă i se transmite array-ul nostru ipotetic cu trei elemente și o lungime de 248, va apela funcția doar de trei ori, nu de 248 de ori. Dacă așa doriți să gestionați array-urile rare, .forEach poate fi soluția chiar dacă interpretatorul dvs. suportă for...of.

Ultima opțiune, care funcționează în toate versiunile de JavaScript, este un ciclu de numărare explicit. Pur și simplu numeri de la 0 până la unul mai mic decât lungimea și folosești contorul ca index. Bucla de bază arată astfel:

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

Un avantaj al acestei abordări este că poți alege cum să gestionezi tablourile rare. Codul de mai sus va executa corpul buclei de length ori, cu s setat la undefined pentru orice elemente lipsă, exact ca for..of; dacă în schimb vrei să gestionezi doar elementele efectiv prezente ale unui tablou rar, ca .forEach, poți adăuga un simplu test in pe index:

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

În funcție de optimizările implementării dvs., atribuirea valorii lungimii variabilei locale (spre deosebire de includerea expresiei complete myStringArray.length în condiția buclei) poate face o diferență semnificativă în performanță, deoarece evită o căutare a proprietății de fiecare dată. Este posibil să observați că cache-ul lungimii este realizat în clauza de inițializare a buclei, astfel:

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

Bucla explicită de numărare înseamnă, de asemenea, că ai acces la indexul fiecărei valori, dacă vrei acest lucru. Indexul este trecut, de asemenea, ca un parametru suplimentar funcției pe care o transmiți la forEach, astfel încât îl poți accesa și în acel mod:

myStringArray.forEach( (s,i) => {
   // ... do something with s and i ...
});

for...of nu îți oferă indexul asociat fiecărui obiect, dar atâta timp cât obiectul pe care îl parcurgi este de fapt o instanță de Array (și nu unul dintre celelalte tipuri iterabile pe care for..of le poate folosi), poți folosi metoda Array#entries pentru a-l transforma într-un array de perechi [index, element], și apoi să parcurgi peste acesta:

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

Sintaxa for...in menționată de alții este pentru a parcurge proprietățile unui obiect; deoarece un Array în JavaScript este doar un obiect cu nume de proprietăți numerice (și o proprietate length actualizată automat), teoretic poți parcurge un Array cu aceasta. Dar problema este că nu se limitează la valorile proprietăților numerice (amintește-ți că chiar și metodele sunt de fapt proprietăți a căror valoare este un closure), și nu este garantat că va itera asupra acestora în ordine numerică. Prin urmare, sintaxa for...in nu ar trebui folosită pentru parcurgerea Array-urilor.

Răspunsul #3

Poți folosi map, care este o tehnică de programare funcțională disponibilă și în alte limbaje precum Python și Haskell.

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

Sintaxa generală este:

array.map(func)

În general, func ar lua un parametru, care este un element al array-ului. Dar în cazul JavaScript, poate lua un al doilea parametru care este indexul elementului și un al treilea parametru care este array-ul însuși.

Valoarea returnată de array.map este un alt array, așa că o poți folosi astfel:

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

Și acum x este [10,20,30,40].

Nu trebuie să scrii funcția inline. Ar putea fi o funcție separată.

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

new_list = my_list.map(item_processor);

care ar fi cam echivalent cu:

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

Cu excepția faptului că nu obții new_list.

Răspunsul #4

pentru (const s din myStringArray) {

(Răspunzând direct la întrebarea ta: acum poți!)

Cele mai multe alte răspunsuri sunt corecte, dar ele nu menționează (la momentul scrierii acestui text) că ECMAScript 6 2015 aduce un nou mecanism pentru efectuarea iterării, bucla for..of.

Această nouă sintaxă este cea mai elegantă modalitate de a parcurge un array în JavaScript (atâta timp cât nu ai nevoie de indexul de iterare).

În prezent funcționează cu Firefox 13+, Chrome 37+ și nu funcționează nativ cu alte browsere (vezi compatibilitatea browserelor mai jos). Din fericire, avem compilatoare JavaScript (cum ar fi Babel) care ne permit să folosim funcționalități de generație următoare chiar de azi.

Funcționează și pe Node.js (l-am testat pe versiunea 0.12.0).

Iterarea unui tablou

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

Iterarea unui array de obiecte

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

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

Iterarea unui generator:

(exemplu extras de pe 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 (const n of fibonacci()) {
  console.log(n);
  // Truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Tabel de compatibilitate: http://kangax.github.io/compat-table/es6/#test-for..of_loops

Specificație: http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}

Răspunsul #5

În JavaScript nu este recomandat să parcurgi un Array cu un loop for-in, dar este mai bine să folosești un loop for precum:

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

Este optimizat și ("cache-uind" lungimea array-ului). Dacă doriți să aflați mai multe, citiți postarea mea despre subiect.

Răspunsul #6

6 metode diferite de a parcurge matricea

Poți parcurge un array prin multe metode diferite. Mi-am ordonat cele 6 metode preferate de la cea mai bună la cea mai puțin bună.

1. Utilizarea buclei for în JavaScript

Când este vorba doar de a parcurge un array, bucla for este prima mea alegere.

let array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
  console.log(array[i]);
}

2. Folosind bucla forEach

Bucla forEach este o modalitate modernă de a parcurge un array. De asemenea, oferă mai multă flexibilitate și control asupra array-ului și elementelor.

let array = [1, 2, 3, 4, 5];
array.forEach((element) => {
  console.log(element);
});

3. Folosind for...of

Bucla for...of îți oferă acces direct la elementele unui tablou.

let array = [1, 2, 3, 4, 5];
for (let element of array) {
  console.log(element);
}

4. Utilizarea buclei for...in

for...in îți oferă o cheie prin care poți accesa elementele unui array.

let array = [1, 2, 3, 4, 5];
for(let index in array){
  console.log(array[index]);
}

5. Utilizarea buclei while

bucla while poate fi folosită pentru a parcurge și array-ul.

let array = [1, 2, 3, 4, 5];
let length = array.length;
while(length > 0){
  console.log(array[array.length - length]);
  length--;
}

6. Utilizarea buclei do...while

La fel, folosesc bucla do...while

let array = [1, 2, 3, 4, 5];
let length = array.length;
do {
  console.log(array[array.length - length]);
  length--;
}
while (length > 0)

Răspunsul #7

Opera, Safari, Firefox și Chrome împărtășesc acum un set de metode Array îmbunătățite pentru optimizarea multor bucle comune.

S-ar putea să nu aveți nevoie de toate, dar ele pot fi foarte utile, sau ar fi dacă fiecare browser le-ar suporta.

Mozilla Labs a publicat algoritmii pe care îi folosesc atât ei, cât și WebKit, astfel încât să îi poți adăuga tu însuți.

filter returnează un array de elemente care satisfac o anumită condiție sau test.

every returnează true dacă fiecare membru al array-ului trece testul.

some returnează true dacă oricare trece testul.

forEach rulează o funcție pentru fiecare membru al unui array și nu returnează nimic.

map este ca forEach, dar returnează un tablou cu rezultatele operației pentru fiecare element.

Toate aceste metode iau o funcție ca prim argument și au un al doilea argument opțional, care este un obiect căruia doriți să îi impuneți sfera asupra elementelor din array pe măsură ce trec prin funcție.

Ignoră-l până ai nevoie de el.

indexOf și lastIndexOf găsesc poziția corespunzătoare a primului sau ultimului element care se potrivește exact cu argumentul său.

(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;
})();

Răspuns #8

Introducere

De pe vremea când eram la facultate, am programat în Java, JavaScript, Pascal, ABAP, PHP, Progress 4GL, C/C++ și, posibil, în câteva alte limbaje la care nu mă pot gândi acum.

Deși fiecare dintre ele are propriile idiosincrasii lingvistice, fiecare dintre aceste limbi împărtășește multe dintre aceleași concepte de bază. Astfel de concepte includ proceduri/funcții, instrucțiuni IF, bucle FOR și bucle WHILE.


Un for-loop tradițional

Un ciclu for tradițional are trei componente:

  1. Inițializarea: executată înainte ca blocul look să fie executat prima dată
  2. Condiția: verifică o condiție de fiecare dată înainte ca blocul buclei să fie executat și părăsește bucla dacă este falsă
  3. Gândul ulterior: se execută de fiecare dată după ce blocul buclei este executat

Aceste trei componente sunt separate între ele printr-un simbol ;. Conținutul pentru fiecare dintre aceste trei componente este opțional, ceea ce înseamnă că următorul este cel mai minimal for posibil:

for (;;) {
    // Do stuff
}

Desigur, va trebui să incluzi un if(condition === true) { break; } sau un if(condition === true) { return; } undeva în interiorul acelui for-loop pentru a-l opri din rulare.

De obicei, totuși, inițializarea este folosită pentru a declara un index, condiția este folosită pentru a compara acel index cu o valoare minimă sau maximă, iar gândirea ulterioară este folosită pentru a incrementa indexul:

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

Folosind un for tradițional pentru a parcurge un array

Modul tradițional de a parcurge un array este acesta:

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

Sau, dacă preferi să faci bucla invers, faci asta:

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

Există, totuși, multe variații posibile, cum ar fi, de exemplu, aceasta:

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

...sau acesta...

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

...sau acesta:

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

Oricare funcționează cel mai bine depinde în mare măsură atât de gustul personal, cât și de cazul specific de utilizare pe care îl implementați.

Rețineți că fiecare dintre aceste variații este acceptată de toate browserele, inclusiv cele foarte, foarte vechi!


O buclă while

O alternativă la un for loop este un while loop. Pentru a parcurge un array, ai putea face asta:

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

La fel ca buclele tradiționale for, buclele while sunt suportate chiar și de cele mai vechi browsere.

De asemenea, rețineți că fiecare buclă while poate fi rescrisă ca o buclă for. De exemplu, bucla while de mai sus se comportă exact la fel ca această buclă for:

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

For...in și for...of

În JavaScript, poți să faci asta și:

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

Acesta ar trebui folosit cu precauție, totuși, deoarece nu se comportă la fel ca un for tradițional în toate cazurile și există efecte secundare potențiale care trebuie luate în considerare. Consultați De ce utilizarea „for...in” pentru iterarea unui array este o idee proastă? pentru mai multe detalii.

Ca alternativă la for...in, există acum și for...of. Exemplul următor arată diferența dintre un ciclu for...of și un ciclu for...in:

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
}

De asemenea, trebuie să iei în considerare că nicio versiune de Internet Explorer nu suportă for...of (Edge 12+ o face) și că for...in necesită cel puțin Internet Explorer 10.


Array.prototype.forEach()

O alternativă la buclele for este Array.prototype.forEach(), care folosește următoarea sintaxă:

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

Array.prototype.forEach() este suportat de toate browserele moderne, precum și de Internet Explorer 9 și versiunile ulterioare.


Biblioteci

În cele din urmă, multe biblioteci de utilități au și propria lor variație foreach. Cât știu eu, cele trei cele mai populare sunt acestea:

jQuery.each(), în jQuery:

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

_.each(), în Underscore.js:

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

_.forEach(), în Lodash:

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

Răspunsul #9

Folosește bucla while...

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

Înregistrează: 'unu', 'doi' și 'trei'

I pentru ordinea inversă, un ciclu și mai eficient:

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

Înregistrează: 'trei', 'doi' și 'unu'

Sau clasicul buclă for:

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

Înregistrează: 'unu','doi','trei'

Referință: Google Closure: Cum să nu scrii JavaScript

Răspuns #10

Dacă vrei un mod succint de a scrie un ciclu rapid și poți itera în ordine inversă:

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

Acest lucru are avantajul de a memora în cache lungimea (similar cu for (var i=0, len=myArray.length; i<len; ++i) și spre deosebire de for (var i=0; i<myArray.length; ++i)) în timp ce necesită mai puține caractere de tastat.

Sunt chiar și unele situații în care ar trebui să iterezi în ordine inversă, cum ar fi atunci când iterezi peste un NodeList activ unde intenționezi să elimini elemente din DOM în timpul iterării.

Răspuns #11

Câteva cazuri de utilizare a parcurgerii unui array în modul programării funcționale în JavaScript:

1. Doar parcurge un tablou

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

Notă: Array.prototype.forEach() nu este în mod strict o modalitate funcțională, deoarece funcția pe care o primește ca parametru de intrare nu este destinată să returneze o valoare, ceea ce astfel nu poate fi considerată o funcție pură.

2. Verificați dacă vreunul dintre elementele dintr-un array trece un test

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3. Transformă într-un nou tablou

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

Notă: Metoda map() creează un nou array cu rezultatele apelării unei funcții furnizate pe fiecare element din array-ul apelant.

4. Rezumați o proprietate particulară și calculați media acesteia

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5. Creează un nou array bazat pe original, dar fără a-l modifica

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6. Numărați numărul fiecărei categorii

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7. Extrage un subset dintr-un array pe baza unor criterii particulare

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

Notă: Metoda filter() creează un nou array cu toate elementele care trec testul implementat de funcția furnizată.

8. Sortează un șir

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

9. Găsiți un element într-un tablou

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

Metoda Array.prototype.find() returnează valoarea primului element din array care satisface funcția de testare furnizată.

Referințe

  • Array.prototype.some()
  • Array.prototype.forEach()
  • Array.prototype.map()
  • Array.prototype.filter()
  • Array.prototype.sort()
  • Sintaxa spread
  • Array.prototype.find()

Răspunsul #12

Da, poți face același lucru în JavaScript folosind un ciclu, dar nu te limitezi doar la asta. Există multe moduri de a parcurge un array în JavaScript. Imaginează-ți că ai acest array mai jos și ai dori să faci un ciclu peste el:

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

Acestea sunt soluțiile:

1) Bucla for

Un loop for este o modalitate comună de a parcurge array-urile în JavaScript, dar nu este considerat cea mai rapidă soluție pentru array-urile mari:

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

2) Bucla while

Un ciclu while este considerat cea mai rapidă metodă de a parcurge tablouri mari, dar este de obicei mai puțin folosit în codul JavaScript:

let i=0;

while (arr.length>i) {
    console.log(arr[i]);
    i++;
}

3) Do while
Un do while face același lucru ca while cu unele diferențe de sintaxă, după cum urmează:

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

Acestea sunt principalele moduri de a face bucle în JavaScript, dar există câteva alte modalități de a face acest lucru.

De asemenea, folosim un ciclu for in pentru a parcurge obiectele în JavaScript.

De asemenea, uită-te la funcțiile map(), filter(), reduce() etc. pe un Array în JavaScript. Ele pot face lucrurile mult mai repede și mai bine decât folosirea while și for.

Acesta este un articol bun dacă îți place să înveți mai multe despre funcțiile asincrone peste array-uri în JavaScript.

Programarea funcțională a făcut destul de multă vâlvă în lumea dezvoltării în zilele noastre. Și pe bună dreptate: Tehnicile funcționale te pot ajuta să scrii cod mai declarativ, care este mai ușor de înțeles dintr-o privire, de refactorizat și de testat.

Unul dintre pilonii programării funcționale este utilizarea ei specială a listelor și a operațiilor pe liste. Și aceste lucruri sunt exact ceea ce par a fi: matrice de obiecte și lucrurile pe care le faci cu ele. Dar modul de gândire funcțional le tratează puțin diferit față de cum te-ai aștepta.

Acest articol va analiza îndeaproape ceea ce îmi place să numesc operațiunile „cele trei mari” pentru liste: map, filter și reduce. A înțelege aceste trei funcții este un pas important către abilitatea de a scrie cod funcțional curat și deschide ușile către tehnicile extrem de puternice ale programării funcționale și reactive.

De asemenea, înseamnă că nu va trebui să scrii niciodată din nou un ciclu for.

Citește mai mult>> aici:

Răspunsul #13

Există o modalitate de a face acest lucru în care ai foarte puțin domeniu implicit în bucla ta și renunți la variabilele suplimentare.

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

Sau dacă vrei cu adevărat să obții id-ul și să ai un for loop cu adevărat clasic:

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
}

Toate browserele moderne suportă metodele iterator forEach, map, reduce, filter și o mulțime de alte metode pe prototipul Array.

Răspuns #14

Există diverse moduri de a parcurge un array în JavaScript.

Buclă generică:

var i;
for (i = 0; i < substr.length; ++i) {
    // Do something with `substr[i]`
}

forEach din ES5:

substr.forEach(function(item) {
    // Do something with `item`
});

jQuery.each:

jQuery.each(substr, function(index, item) {
    // Do something with `item` (or `this` is also `item` if you like)
});

Aruncă o privire aici pentru informații detaliate sau poți de asemenea să verifici MDN pentru parcurgerea unui array în JavaScript și folosind jQuery verifică jQuery pentru each.

Răspuns #15

Bucle de array:

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

Bucle de obiect:

for(var prop in obj){
    var propValue = obj[prop];
    console.log(propValue);
}

Răspuns #16

Aș recomanda cu căldură utilizarea bibliotecii Underscore.js. Aceasta vă oferă diverse funcții pe care le puteți folosi pentru a itera peste array-uri/colecții.

De exemplu:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

Răspunsul #17

Dacă cineva este interesat de partea de performanță a multiplelor mecanisme disponibile pentru iterarea array-urilor, am pregătit următoarele teste JSPerf:

https://jsperf.com/fastest-array-iterator

Rezultate :

Iteratorul tradițional for() este de departe cea mai rapidă metodă, în special atunci când este folosit cu lungimea array-ului memorată în cache.

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

for(let i=0, size=arr.length; i<size; i++){
    // Do something
}

Metodele Array.prototype.forEach() și Array.prototype.map() sunt cele mai lente aproximații, probabil ca urmare a suprasarcinii apelului de funcție.

Răspunsul #18

Dacă folosești biblioteca jQuery, ia în considerare utilizarea http://api.jquery.com/jQuery.each/

Din documentație:

jQuery.each( colecție, callback(indexÎnArray, valoareaElementului) )

Returnează: Obiect

Descriere: O funcție generică de iterator, care poate fi utilizată pentru a itera fără probleme atât asupra obiectelor, cât și asupra array-urilor. Array-urile și obiectele similare cu array care au o proprietate length (cum ar fi obiectul arguments al unei funcții) sunt iterate prin index numeric, de la 0 la length-1. Alte obiecte sunt iterate prin proprietățile lor denumite.

Funcția $.each() nu este aceeași cu $(selector).each(), care este folosită exclusiv pentru a itera asupra unui obiect jQuery. Funcția $.each() poate fi folosită pentru a itera asupra oricărei colecții, fie că este un map (obiect JavaScript) sau un array. În cazul unui array, funcția de callback primește de fiecare dată un index al array-ului și o valoare corespunzătoare din array. (Valoarea poate fi accesată, de asemenea, prin cuvântul cheie this, dar JavaScript va înveli întotdeauna valoarea this ca un Object, chiar dacă este o valoare simplă de tip șir de caractere sau număr.) Metoda returnează primul său argument, obiectul asupra căruia s-a iterat.

Răspuns #19

Nu am văzut încă această variație, care îmi place personal cel mai mult:

Având un array:

var someArray = ["some", "example", "array"];

Poți să parcurgi acest lucru în buclă fără a accesa vreodată proprietatea length:

for (var i=0, item; item=someArray[i]; i++) {
  // item is "some", then "example", then "array"
  // i is the index of item in the array
  alert("someArray[" + i + "]: " + item);
}

Vedeți acest JsFiddle care demonstrează acest lucru: http://jsfiddle.net/prvzk/

Acest lucru funcționează doar pentru tablouri care nu sunt rare. Asta înseamnă că există efectiv o valoare la fiecare index din tablou. Totuși, am descoperit că, în practică, aproape niciodată nu folosesc tablouri rare în JavaScript... În astfel de cazuri, de obicei, este mult mai ușor să folosești un obiect ca hartă/hashtable. Dacă ai un tablou rar și vrei să parcurgi 0 .. length-1, ai nevoie de construcția for (var i=0; i<someArray.length; ++i), dar încă ai nevoie de un if în interiorul buclei pentru a verifica dacă elementul de la indexul curent este efectiv definit.

De asemenea, așa cum menționează CMS într-un comentariu de mai jos, poți folosi asta doar pe array-uri care nu conțin niciun fel de valori falsy. Array-ul de șiruri din exemplu funcționează, dar dacă ai șiruri goale, sau numere care sunt 0 sau NaN, etc., bucla se va întrerupe prematur. Din nou, în practică, pentru mine asta aproape niciodată nu este o problemă, dar este ceva de reținut, ceea ce face ca aceasta să fie o buclă la care să te gândești înainte să o folosești... Asta poate să o descalifice pentru unii oameni :)

Ce îmi place la acest ciclu este:

  • Este scurt de scris
  • Nu este nevoie să accesați (și cu atât mai puțin să memorați în cache) proprietatea length
  • Elementul de accesat este definit automat în corpul buclei sub numele pe care îl alegi.
  • Se combină foarte natural cu array.push și array.splice pentru a folosi tablouri ca liste/stive

Motivul pentru care acest lucru funcționează este că specificația array-ului impune ca atunci când citești un element de la un index >= lungimii array-ului, va returna undefined. Când scrii într-o astfel de locație, va actualiza de fapt lungimea.

Pentru mine, această construcție imită cel mai mult sintaxa Java 5 pe care o iubesc:

for (String item : someArray) {
}

... cu beneficiul suplimentar de a ști și despre indicele curent din buclă

Răspuns #20

Există 4 moduri de a parcurge un array:

// 1: for

for (let i = 0; i < arr.length; ++i) {
  console.log(arr[i]);
}

// 2: forEach

arr.forEach((v, i) => console.log(v));

// 3: for in

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

// 4: for of

for (const v of arr) {
  console.log(v);
}

Rezumat: soluțiile 1 și 3 creează o variabilă suplimentară, 2 - creează un context de funcție suplimentar. Cea mai bună metodă este a 4-a - "for of".

Răspuns #21

Ezoteric

let a= ["Hello", "World"];

while(a.length) { console.log( a.shift() ); }

Test de performanță

Astăzi (2022-11-13) efectuez un test pe Chrome 107, Safari 15.2 și Firefox 106 pe soluțiile alese.

Concluzii

  • soluțiile C și D sunt rapide sau cele mai rapide pe toate browserele pentru toate array-urile.
  • soluțiile A și B sunt cele mai lente pe toate browserele pentru toate array-urile

Rezultate

Detalii

Efectuez 3 teste:

  • mic - pentru un array de 2 elemente (ca OP) - poți să îl rulezi aici
  • mediu - pentru un array de 10.000 de elemente și - îl poți rula aici
  • mare - pentru un tablou de 100K de elemente - poți să-l rulezi aici

Fragmentul de mai jos prezintă codul utilizat în test.

function A(a) {
  let r=0;
  while(a.length) r+= a.shift().length;
  return r;
}

function B(a) {
  let r=0;
  for(i in a) r+= a[i].length;
  return r;
}

function C(a) {
  let r=0;
  for(x of a) r+= x.length;
  return r;
}

function D(a) {
  let r=0;
  for (i=0; i<a.length; ++i) r+= a[i].length;
  return r;

}

function E(a) {
  let r=0;
  a.forEach(x=> r+= x.length);
  return r;
}

let arr= ["Hello", "World!"];
[A,B,C,D,E].forEach(f => console.log(`${f.name}: ${f([...arr])}`))

Iată rezultate exemplu pentru Chrome pentru un array mediu:

Răspunsul #22

Există o metodă de a itera doar peste proprietățile proprii ale obiectului, fără a include pe cele din prototip:

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

dar totuși va itera peste proprietățile definite personal.

În JavaScript orice proprietate personalizată poate fi atribuită oricărui obiect, inclusiv unui tablou.

Dacă cineva dorește să parcurgă un array rar, ar trebui folosit for (var i=0; i < array.length; i++) if (i in array) sau array.forEach cu es5shim.

Răspunsul #23

Cea mai elegantă și rapidă cale

var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}

http://jsperf.com/native-loop-performance/8


Editat (pentru că am greșit)


Compararea metodelor pentru a parcurge un tablou de 100000 de elemente și a efectua o operațiune minimă cu valoarea nouă de fiecare dată.

  • http://jsben.ch/#/BQhED

Pregătire:

<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        // Fake function with minimal action on the value
        var tmp = 0;
        var process = function(value) {
            tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
        };
        
        // Declare the test Array
        var arr = [];
        for (var i = 0; i < 100000; i++)
            arr[i] = i;
    };
</script>

Teste:

<a href="http://jsperf.com/native-loop-performance/16" 
   title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>

Răspunsul #24

Există câteva moduri de a face acest lucru în JavaScript. Primele două exemple sunt mostre de JavaScript. Al treilea folosește o bibliotecă JavaScript, adică jQuery, folosind funcția .each().

var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
  alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Răspunsul #25

Abordarea optimizată este să memorezi lungimea array-ului și să folosești tiparul cu o singură variabilă, inițializând toate variabilele cu un singur cuvânt cheie var.

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

    // Do something
}

Dacă ordinea de iterare nu contează, atunci ar trebui să încerci bucla inversă. Este cea mai rapidă, deoarece reduce testarea condițiilor și decrementarea este într-o singură instrucțiune:

var i,myStringArray = ["item1","item2"];
for (i =  myStringArray.length; i--) {
    alert(myStringArray[i]);
}

Sau mai bine și mai curat să folosești un while loop:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // Do something with fruits[i]
}

Răspuns #26

În JavaScript, există atât de multe soluții pentru a parcurge un array.

Codurile de mai jos sunt populare

/** Declare inputs */
const items = ['Hello', 'World']

/** Solution 1. Simple for */
console.log('solution 1. simple for')

for (let i = 0; i < items.length; i++) {
  console.log(items[i])
}

console.log()
console.log()

/** Solution 2. Simple while */
console.log('solution 2. simple while')

let i = 0
while (i < items.length) {
  console.log(items[i++])
}

console.log()
console.log()

/** Solution 3. forEach*/
console.log('solution 3. forEach')

items.forEach(item => {
  console.log(item)
})

console.log()
console.log()

/** Solution 4. for-of*/
console.log('solution 4. for-of')

for (const item of items) {
  console.log(item)
}

console.log()
console.log()

Răspunsul #27

Cea mai bună metodă, după părerea mea, este să folosești funcția Array.forEach. Dacă nu poți folosi asta, aș sugera să obții polyfill-ul de pe MDN. Pentru a-l face disponibil, este cu siguranță cea mai sigură modalitate de a itera peste un array în JavaScript.

Array.prototype.forEach()

Deci, așa cum au sugerat și alții, acesta este aproape întotdeauna ceea ce vrei:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

Aceasta asigură că tot ce ai nevoie în domeniul de procesare al matricei rămâne în acel domeniu și că procesezi doar valorile matricei, nu proprietățile obiectului și alți membri, ceea ce face for .. in.

Folosirea unui loop obișnuit de tip C for funcționează în majoritatea cazurilor. Este doar important să reții că tot ce se află în interiorul loop-ului împarte domeniul său (scope) cu restul programului tău, acoladele { } nu creează un domeniu nou.

Prin urmare :

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

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

alert(i);

va afișa "11" - ceea ce poate sau nu poate fi ceea ce doriți.

Un exemplu jsFiddle funcțional: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/

Răspunsul #28

Dacă vrei să folosești jQuery, acesta are un exemplu frumos în documentația sa:

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });

Răspunsul #29

Nu este 100% identic, dar asemănător:

   var myStringArray = ['Hello', 'World']; // The array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }

Răspuns #30

De exemplu, am folosit în consola Firefox:

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})

Poți folosi querySelectorAll pentru a obține același rezultat

document.querySelectorAll('pre').forEach( (e) => { 
   console.log(e.textContent);
})
<pre>text 1</pre>
<pre>text 2</pre>
<pre>text 3</pre>