Parcourez un tableau en JavaScript

3148

En Java, vous pouvez utiliser une forboucle pour parcourir des objets dans un tableau comme suit:

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

Pouvez-vous faire de même en JavaScript?

Mark Szymanski
la source
5
Ok, donc je suis un peu confus, c'est ok d'utiliser la boucle for améliorée lorsque vous accédez aux objets? Et utiliser un séquentiel pour en remplir un? Est-ce correct?
Mark Szymanski
45
non, c'est vraiment simple, les objets de tableau ont des index numériques, donc vous voulez parcourir ces index dans l'ordre numérique, une boucle séquentielle garantit que, la boucle améliorée énumère les propriétés des objets, sans ordre spécifique, et elle énumère également les propriétés héritées. .. pour itérer sur des tableaux, les boucles séquentielles sont toujours recommandées ...for-in
CMS
2
connexes - stackoverflow.com/questions/5349425/…
jondavidjohn
6
jsben.ch/#/Q9oD5 <= Voici un benchmark d'un tas de solutions pour boucler à travers des tableaux
EscapeNetscape
3
@CMS Non, ce n'est pas vraiment simple. C'est vraiment simple dans toutes les autres langues. C'est ridiculement complexe dans JS, où vous en avez inet ofqui peut être utilisé et faire des choses différentes. Ensuite, vous avez également forEachet la boucle basée sur l'index laid et ennuyeux. Toutes les autres langues modernes permettent de parcourir une collection facilement et sans aucune surprise ni confusion. JS le pourrait aussi, mais ce n'est pas le cas.
jpmc26

Réponses:

3966

Vous avez plusieurs options:

1. forBoucle séquentielle :

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

Avantages

  • Fonctionne sur tous les environnements
  • Vous pouvez utiliser breaket continuecontrôler les instructions de flux

Les inconvénients

  • Trop verbeux
  • Impératif
  • Facile à avoir des erreurs ponctuelles (parfois aussi appelé erreur de poteau de clôture )

2. Array.prototype.forEach

La spécification ES5 a introduit de nombreuses méthodes de tableau bénéfiques, l'une d'entre elles, Array.prototype.forEachet elle nous donne un moyen concis d'itérer sur un tableau:

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

Étant près de dix ans au moment de la publication de la spécification ES5 (décembre 2009), elle a été implémentée par presque tous les moteurs modernes dans les environnements de bureau, de serveur et mobiles, il est donc sûr de les utiliser.

Et avec la syntaxe de la fonction flèche ES6, c'est encore plus succinct:

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

Les fonctions fléchées sont également largement implémentées, sauf si vous prévoyez de prendre en charge les anciennes plates-formes (par exemple, IE11); vous pouvez également aller en toute sécurité.

Avantages

  • Très court et succinct.
  • Déclaratif

Les inconvénients

  • Impossible d'utiliser break/continue

Normalement, vous pouvez remplacer la nécessité de breaksortir des boucles impératives en filtrant les éléments du tableau avant de les itérer, par exemple:

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

Gardez à l'esprit que si vous itérez un tableau pour en construire un autre , vous devriez utiliser map, j'ai vu cet anti-modèle tant de fois.

Anti-motif:

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

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

Cas d'utilisation approprié de la carte :

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

console.log(doubled);

En outre, si vous essayez de réduire le tableau à une valeur, par exemple, vous souhaitez additionner un tableau de nombres, vous devez utiliser la méthode de réduction .

Anti-motif:

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

Utilisation appropriée de réduire :

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

console.log(sum);

3. ES6 for-ofdéclaration

La norme ES6 introduit le concept d'objets itérables et définit une nouvelle construction pour parcourir les données, l' for...ofinstruction.

Cette instruction fonctionne pour tout type d'objet itérable et également pour les générateurs (tout objet ayant une [Symbol.iterator]propriété).

Les objets tableau sont par définition des itérables intégrés dans ES6, vous pouvez donc utiliser cette instruction sur eux:

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

Avantages

  • Il peut parcourir une grande variété d'objets.
  • Peut utiliser des instructions de contrôle de flux normales ( break/ continue).
  • Utile pour itérer des valeurs asynchrones en série.

Les inconvénients

Ne pas utiliser for...in

@zipcodeman suggère l'utilisation de l' for...ininstruction, mais pour itérer les tableaux for-in, cette instruction est destinée à énumérer les propriétés des objets.

Il ne doit pas être utilisé pour les objets de type tableau car:

  • L'ordre d'itération n'est pas garanti; les index de tableau ne peuvent pas être visités dans l'ordre numérique.
  • Les propriétés héritées sont également énumérées.

Le deuxième point est que cela peut vous poser beaucoup de problèmes, par exemple, si vous étendez l' Array.prototypeobjet pour y inclure une méthode, cette propriété sera également énumérée.

Par exemple:

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

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

Le code ci-dessus consolera le journal "a", "b", "c" et "foo!".

Cela peut être particulièrement problématique si vous utilisez une bibliothèque qui dépend fortement de l'augmentation des prototypes natifs (comme MooTools).

L' for-ininstruction comme je l'ai déjà dit est là pour énumérer les propriétés des objets, par exemple:

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

Dans l'exemple ci-dessus, la hasOwnPropertyméthode vous permet d'énumérer uniquement ses propres propriétés , c'est tout, uniquement les propriétés que possède physiquement l'objet, pas de propriétés héritées.

Je vous recommande de lire l'article suivant:

CMS
la source
21
C'est la raison (par CMS lui-même) stackoverflow.com/questions/1885317/…
OscarRyz
15
@DoubleGras, je pense que c'est une opinion qui n'est pas partagée par tout le monde. Voir: stackoverflow.com/questions/5752906/… ou groups.google.com/forum/?fromgroups#!topic/jsmentors/…
Matthijs Wessels
3
Quiconque pense que vous devez mettre en cache la longueur ... Veuillez voir ma réponse, vous n'avez même pas besoin d'y accéder une seule fois, sans parler de le mettre en cache: pour (var i = 0, item; item = myStringArray [i]; i ++) {/ * utiliser l'élément ici * /}
Stijn de Witt
15
@StijndeWitt Non, parce que les pauses si vous avez des « Falsey » valeurs dans votre tableau: false, undefined, 0, "", NaN.
Phrogz
6
jsperf.com/caching-array-length/4 Voici un test pour voir s'il vaut la peine de mettre en cache la longueur d'un tableau dans une boucle Javascript
Enrico
1116

Oui, en supposant que votre implémentation inclut la fonctionnalité for...of introduite dans ECMAScript 2015 (la version "Harmony") ... ce qui est une hypothèse assez sûre de nos jours.

Cela fonctionne comme ceci:

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

Ou mieux encore, car ECMAScript 2015 fournit également des variables de portée bloc:

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

(La variable sest différente à chaque itération, mais peut toujours être déclarée constà l'intérieur du corps de la boucle tant qu'elle n'y est pas modifiée.)

Une note sur les tableaux clairsemés: un tableau en JavaScript peut ne pas réellement stocker autant d'éléments que rapporté par son length; ce nombre déclaré est simplement supérieur de un à l'indice le plus élevé auquel une valeur est stockée. Si le tableau contient moins d'éléments que ne l'indique sa longueur, il est dit qu'il est rare . Par exemple, il est parfaitement légitime d'avoir un tableau avec des éléments uniquement aux index 3, 12 et 247; le rapport lengthd'un tel tableau est signalé comme 248, bien qu'il ne stocke en réalité que 3 valeurs. Si vous essayez d'accéder à un élément à tout autre index, le tableau semblera y avoir la undefinedvaleur. Donc, quand vous voulez "boucler" un tableau, vous avez une question à répondre: voulez-vous boucler sur toute la plage indiquée par sa longueur et son processusundefineds pour tout élément manquant, ou souhaitez-vous uniquement traiter les éléments réellement présents? Il existe de nombreuses applications pour les deux approches; cela dépend simplement de la raison pour laquelle vous utilisez le tableau.

Si vous parcourez un tableau avec for.. of, le corps de la boucle est exécuté lengthfois et la variable de contrôle de boucle est définie sur undefinedpour tous les éléments qui ne sont pas réellement présents dans le tableau. Selon les détails de votre code "faire quelque chose avec", ce comportement peut être ce que vous voulez, mais sinon, vous devez utiliser une approche différente.

Bien sûr, certains développeurs ont pas d'autre choix que d'utiliser de toute façon une approche différente, parce que , pour une raison quelconque , ils ciblez une version de JavaScript qui ne supporte pas encore for... of.

Tant que votre implémentation JavaScript est conforme à l' édition précédente de la spécification ECMAScript (qui exclut, par exemple, les versions d'Internet Explorer avant 9), vous pouvez utiliser la Array#forEachméthode itérateur au lieu d'une boucle. Dans ce cas, vous passez une fonction à appeler sur chaque élément du tableau:

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

Contrairement à for... of, .forEachn'appelle la fonction que pour les éléments réellement présents dans le tableau. Si passé notre tableau hypothétique avec trois éléments et une longueur de 248, il n'appellera la fonction que trois fois, pas 248 fois. Il distingue également les éléments manquants des éléments réellement définis sur undefined; pour ce dernier, il appellera toujours la fonction, en passant undefinedcomme argument. Si cela est la façon dont vous voulez gérer des tableaux rares, .forEachpeut - être le chemin à parcourir , même si vos supports d'interprétation for... of.

La dernière option, qui fonctionne dans toutes les versions de JavaScript, est une boucle de comptage explicite . Vous comptez simplement de 0 à un de moins que la longueur et utilisez le compteur comme index. La boucle de base ressemble à ceci:

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

Un avantage de cette approche est que vous pouvez choisir comment gérer les tableaux clairsemés; le code ci - dessus courra le corps de la boucle les pleins lengthtemps, avec sjeu à undefinedpour les éléments manquants, tout comme for.. of. Si vous souhaitez gérer uniquement les éléments réellement présents d'un tableau fragmenté, comme .forEach, vous pouvez ajouter un intest simple sur l'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 ...
  }
}

L'attribution de la valeur de longueur à la variable locale (au lieu d'inclure l' myStringArray.lengthexpression complète dans la condition de boucle) peut faire une différence significative dans les performances car elle ignore une recherche de propriété à chaque fois; en utilisant Rhino sur ma machine, l'accélération est de 43%.

Vous pouvez voir la mise en cache de longueur effectuée dans la clause d'initialisation de boucle, comme ceci:

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

La boucle de comptage explicite signifie également que vous avez accès à l'index de chaque valeur, si vous le souhaitez. L'index est également passé en tant que paramètre supplémentaire à la fonction à laquelle vous passez forEach, vous pouvez donc y accéder également:

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

for... ofne vous donne pas l'index associé à chaque objet, mais tant que l'objet que vous parcourez est en fait un Array( for.. offonctionne pour d'autres types itérables qui peuvent ne pas avoir cette méthode), vous pouvez utiliser le tableau #entries, méthode pour le changer en un tableau de paires [index, item], puis itérer sur cela:

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

La syntaxe for... inmentionnée par d'autres est pour boucler sur les propriétés d'un objet; puisqu'un tableau en JavaScript n'est qu'un objet avec des noms de propriétés numériques (et une lengthpropriété mise à jour automatiquement ), vous pouvez théoriquement boucler sur un tableau avec lui. Mais le problème est qu'il ne se limite pas aux valeurs des propriétés numériques (rappelez-vous que même les méthodes ne sont en fait que des propriétés dont la valeur est une fermeture), et il n'est pas non plus garanti d'itérer sur celles dans l'ordre numérique. Par conséquent, la syntaxe for... nein doit pas être utilisée pour parcourir les tableaux.

Mark Reed
la source
21
Notez que certains interprètes (par exemple V8) mettent automatiquement en cache la longueur du tableau si le code est appelé suffisamment de fois et qu'il détecte que la longueur n'est pas modifiée par la boucle. Bien que la mise en cache de la longueur soit toujours agréable, elle peut ne pas augmenter la vitesse lorsque votre code est appelé suffisamment de fois pour réellement faire la différence.
Phrogz
2
@ mark-reed Pourriez-vous expliquer pourquoi vous l'avez utilisé i in myStringArraydans votre exemple? Comment cela peut-il être faux?
Denis V
2
@DenisV: faux. a=[1,2,3,4]; delete a[2]; for (j in a) { console.log(j); } sorties 0, 1, 3 et 4. a.lengthest toujours 5.
Mark Reed
1
Je ne suggère pas for j in a. Je démontre que le inchèque n'est pas redondant, comme vous l'avez prétendu, en montrant tous les index et en montrant qu'il y en a un entre 0 et length-1qui n'est pas là. J'aurais pu également imprimer 2 in a, ce qui est effectivement le cas false, même si vous avez dit que c'était impossible.
Mark Reed
2
@GrijeshChauhan - correct. Par exemple, IE via la version 8 ne le prend pas en charge. Voir cette question .
Mark Reed
442

Vous pouvez utiliser map, qui est une technique de programmation fonctionnelle qui est également disponible dans d'autres langages comme Python et Haskell .

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

La syntaxe générale est:

array.map(func)

En général func, prendrait un paramètre, qui est un élément du tableau. Mais dans le cas de JavaScript, il peut prendre un deuxième paramètre qui est l'index de l'élément, et un troisième paramètre qui est le tableau lui-même.

La valeur de retour de array.mapest un autre tableau, vous pouvez donc l'utiliser comme ceci:

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

Et maintenant x l'est [10,20,30,40].

Vous n'avez pas besoin d'écrire la fonction en ligne. Ce pourrait être une fonction distincte.

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

new_list = my_list.map(item_processor);

ce qui serait en quelque sorte équivalent à:

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

Sauf que vous ne comprenez pas new_list.

hasen
la source
7
Non, mais cela peut être plus puissant. vérifier cela: joelonsoftware.com/items/2006/08/01.html
hasen
97
Cet exemple particulier est probablement mieux implémenté en utilisant Array.forEach. mapsert à générer un nouveau tableau.
harto
21
@hasen, la Array.prototype.mapméthode fait partie de la norme ECMAScript 5e édition, n'est pas encore disponible sur toutes les implémentations (par exemple, IE en manque), également pour itérer sur un tableau, je pense que la Array.prototype.forEachméthode est plus sémantiquement correcte ... aussi merci de ne pas '' t suggérer la déclaration for-in, voir ma réponse pour plus de détails :)
CMS
3
La différence entre forEachet mapest que le premier ne renvoie pas les résultats de l'itération. map(parfois alias collect, mais très différent de apply) sert expressément à transformer chaque élément d'un tableau en un résultat correspondant; c'est un mappage 1 à 1 , d'où le nom. Cela fait partie d'une famille entière d'opérations qui incluent reduce(qui produit un seul résultat à partir du tableau entier) et filter(qui produit un sous-ensemble du tableau d'origine) et ainsi de suite. Alors forEachque fait juste quelque chose avec chaque élément, la sémantique n'est pas spécifiée.
Mark Reed du
4
Downvote parce que si vous ne mappez pas réellement quelque chose, alors utiliser [] .map est trompeur. [] .forEach a un sens sémantique et transmet également les trois mêmes arguments à la fonction.
gengkev
120

En JavaScript, il n'est pas conseillé de parcourir un tableau avec une boucle for-in, mais il est préférable d'utiliser une forboucle telle que:

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

Il est également optimisé ("mise en cache" de la longueur du tableau). Si vous souhaitez en savoir plus, lisez mon article sur le sujet .

sebarmeli
la source
2
myArray.forEach (function (obj) {}); est toujours le meilleur
Jan Sverre
une petite amélioration: vous pouvez utiliser à la ++iplace dei++
roberkules
14
++iest une optimisation à l'ancienne que les compilateurs modernes font pour vous dans une boucle for depuis longtemps :) stackoverflow.com/a/1547433/1033348
ngryman
6
Vous devez être prudent en utilisant cette boucle. J'ai commencé à l'utiliser et j'ai eu un bug difficile à suivre à cause d'une erreur que j'ai commise. Si vous imbriquez deux boucles comme celle-ci: jsfiddle.net/KQwmL/1 . Vous devez faire attention à nommer la var len différemment dans les deux boucles, sinon la deuxième boucle écrasera la première len.
Rui Marques
1
Rui Marques - vous pouvez nommer votre variable i_stopou i_endau lieu de len. Il est tout aussi lisible (sinon plus!), Et vous éviterez naturellement ce genre de problème (puisque votre autre boucle obtiendra, par exemple, j_stop).
Chip Hogg
119

pour (soit s de myStringArray) {

(Répondre directement à votre question: maintenant vous pouvez!)

La plupart des autres réponses sont exactes, mais elles ne mentionnent pas (au moment où nous écrivons) que ECMA Script  6  2015 apporte un nouveau mécanisme pour faire l'itération, la for..ofboucle.

Cette nouvelle syntaxe est la manière la plus élégante d'itérer un tableau en javascript (tant que vous n'avez pas besoin de l'index d'itération).

Il fonctionne actuellement avec Firefox 13+, Chrome 37+ et il ne fonctionne pas nativement avec d'autres navigateurs (voir la compatibilité du navigateur ci-dessous). Heureusement, nous avons des compilateurs JS (tels que Babel ) qui nous permettent d'utiliser des fonctionnalités de nouvelle génération aujourd'hui.

Il fonctionne également sur Node (je l'ai testé sur la version 0.12.0).

Itération d'un tableau

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

Itération d'un tableau d'objets

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

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

Itération d'un générateur:

(exemple extrait de 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;
  }
}

Tableau de compatibilité: http://kangax.github.io/es5-compat-table/es6/#For..of loops

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

}

Marlon Bernardes
la source
Si vous utilisez ES6, je suggérerais const sau lieu devar s
joeytwiddle
Dans mes tests sur de grands tableaux, l'utilisation var s of arrest presque le double (1,9x) du temps d'exécution par rapport à l'utilisation d'un simple compteur for-loop et la récupération d'éléments par index dans nodejs
theferrit32
Pourquoi ces trucs bizarres dans la première et la dernière ligne?
Peter Mortensen
91

Opera, Safari, Firefox et Chrome partagent désormais tous un ensemble de méthodes Array améliorées pour optimiser de nombreuses boucles courantes.

Vous n'avez peut-être pas besoin de tous, mais ils peuvent être très utiles, ou le seraient si tous les navigateurs les prenaient en charge.

Mozilla Labs a publié les algorithmes qu'ils utilisent et WebKit , afin que vous puissiez les ajouter vous-même.

Le filtre renvoie un tableau d'éléments qui satisfont à une condition ou à un test.

every renvoie true si chaque membre du tableau réussit le test.

certains retournent vrai si aucun passe le test.

forEach exécute une fonction sur chaque membre du tableau et ne renvoie rien.

map est comme forEach, mais il retourne un tableau des résultats de l'opération pour chaque élément.

Ces méthodes prennent toutes une fonction pour leur premier argument et ont un deuxième argument facultatif, qui est un objet dont vous souhaitez imposer la portée aux membres du tableau lors de leur boucle dans la fonction.

Ignorez-le jusqu'à ce que vous en ayez besoin.

indexOf et lastIndexOf trouvent la position appropriée du premier ou du dernier élément qui correspond exactement à son 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;
})();
kennebec
la source
1
Addition: IE prend en charge forEach depuis la version 9, voir forEach Method MSDN
rwitzel
75

Intro

Depuis mon passage à l'université, j'ai programmé en Java, JavaScript, Pascal, ABAP , PHP, Progress 4GL, C / C ++ et peut-être quelques autres langages auxquels je ne peux pas penser en ce moment.

Bien qu'ils aient tous leurs propres idiosyncrasies linguistiques, chacune de ces langues partage bon nombre des mêmes concepts de base. Ces concepts incluent les procédures / fonctions, les IFinstructions, les FORboucles et les WHILEboucles.


Une forboucle traditionnelle

Une forboucle traditionnelle a trois composantes:

  1. L'initialisation: exécutée avant la première exécution du bloc look
  2. La condition: vérifie une condition à chaque fois avant l'exécution du bloc de boucle et quitte la boucle si elle est fausse
  3. L'après-réflexion: effectuée à chaque fois après l'exécution du bloc de boucle

Ces trois composants sont séparés les uns des autres par un ;symbole. Le contenu de chacun de ces trois composants est facultatif, ce qui signifie que ce qui suit est la forboucle la plus minimale possible:

for (;;) {
    // Do stuff
}

Bien sûr, vous devrez inclure un if(condition === true) { break; } ou un if(condition === true) { return; }quelque part à l'intérieur de cette forboucle pour qu'elle cesse de fonctionner.

Habituellement, cependant, l'initialisation est utilisée pour déclarer un index, la condition est utilisée pour comparer cet index avec une valeur minimale ou maximale, et la réflexion après coup est utilisée pour incrémenter l'index:

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

Utilisation d'une forboucle traditionnelle pour parcourir un tableau

La façon traditionnelle de parcourir un tableau est la suivante:

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

Ou, si vous préférez boucler en arrière, vous procédez comme suit:

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

Il existe cependant de nombreuses variantes possibles, comme par exemple celle-ci:

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

... ou celui-ci ...

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

... ou celui-ci:

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

Celui qui fonctionne le mieux est en grande partie une question de goût personnel et de cas d'utilisation spécifique que vous implémentez.

Notez que chacune de ces variantes est supportée par tous les navigateurs, y compris les très très anciens!


Une whileboucle

Une alternative à une forboucle est une whileboucle. Pour parcourir un tableau, vous pouvez procéder comme suit:

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

Comme les forboucles traditionnelles , les whileboucles sont prises en charge par même les plus anciens des navigateurs.

Notez également que chaque boucle while peut être réécrite sous forme de forboucle. Par exemple, la whileboucle ci-dessus se comporte exactement de la même manière que cette forboucle:

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

For...in et for...of

En JavaScript, vous pouvez également faire ceci:

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

Cependant, cela doit être utilisé avec précaution, car il ne se comporte pas de la même manière qu'une forboucle traditionnelle dans tous les cas, et il existe des effets secondaires potentiels qui doivent être pris en compte. Voir Pourquoi l'utilisation de "for ... in" avec l'itération de tableau est une mauvaise idée? pour plus de détails.

Comme alternative à for...in, il y a maintenant aussi pour for...of. L'exemple suivant montre la différence entre une for...ofboucle et une for...inboucle:

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 plus, vous devez considérer qu'aucune version d'Internet Explorer ne prend en charge for...of( Edge 12+ le fait) et cela for...innécessite au moins Internet Explorer 10.


Array.prototype.forEach()

Une alternative à for-loops est Array.prototype.forEach(), qui utilise la syntaxe suivante:

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

Array.prototype.forEach() est pris en charge par tous les navigateurs modernes, ainsi qu'Internet Explorer 9 et versions ultérieures.


Bibliothèques

Enfin, de nombreuses bibliothèques d'utilitaires ont également leur propre foreachvariante. AFAIK, les trois plus populaires sont les suivantes:

jQuery.each(), dans jQuery :

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

_.each(), dans Underscore.js :

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

_.forEach(), dans Lodash.js :

_.forEach(myArray, function(value, key) {
    console.log(value);
});
John Slegers
la source
68

Utilisez la boucle while ...

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

journaux: «un», «deux», «trois»

Et pour l'ordre inverse, une boucle encore plus efficace

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

journaux: «trois», «deux», «un»

Ou la forboucle classique

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

journaux: «un», «deux», «trois»

Référence: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/

Timo Huovinen
la source
21
Le premier exemple de la syntaxe "while" ne fonctionnera pas si l'un des éléments du tableau est faux.
Chris Cooper
2
... et cette boucle while est équivalente à: for (var i = 0, item; item = items [i]; i ++), ce qui supprime la nécessité de déclarer au préalable les variables d'index et d'item ...
Stijn de Witt
39

Si vous voulez une manière concise d'écrire une boucle rapide et vous pouvez répéter en sens inverse:

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

Cela a l'avantage de mettre en cache la longueur (similaire for (var i=0, len=myArray.length; i<len; ++i)et différente for (var i=0; i<myArray.length; ++i)) tout en étant moins de caractères à taper.

Il y a même des moments où vous devez effectuer une itération inverse, comme lors de l'itération sur une NodeList en direct où vous prévoyez de supprimer des éléments du DOM pendant l'itération.

Phrogz
la source
16
Pour les personnes qui n'obtiennent pas ce qui est si ingénieux: l'expression i-- est d'abord évaluée et permet à la boucle de continuer lorsqu'elle n'est pas fausse ... Ensuite, le compteur est décrémenté. Dès que i devient zéro, il sortira de la boucle car zéro est une valeur fausse en Javascript.
Stijn de Witt
5
faux? Tu veux dire falsey.
Collons
4
J'ai vu le terme faux utilisé par des gens que je considère comme des gourous. Si c'est assez bon pour eux, c'est assez bon pour moi. Aussi, mais déçu de voir que mon commentaire qui est en fait ontopique et ajoute une explication / aperçu obtient 0 votes positifs, mais le commentaire qui met un terme à un terme dans mon commentaire obtient 4. Ah bien, juste une question de priorités, je suppose.
Stijn de Witt
"Mise en cache de la longueur"? La longueur est stockée sous forme d'entier dans le tableau, elle n'est pas mesurée à chaque fois que vous y accédez. Il n'y a aucun avantage ici à copier la valeur de la longueur dans une autre variable.
Mouscellaneous
1
@Mouscellaneous De nos jours, il n'y en a certainement pas; Au cours des années passées, l'itération des tableaux JavaScript mettant en cache la longueur du côté JavaScript (au lieu de s'étendre à travers l'implémentation) était un gain de performance clair (lors de la microoptimisation). Par exemple, for (var i=0,len=array.length;i<len;++i)était une boucle commune et sensible à écrire.
Phrogz
36

Certains cas d'utilisation de bouclage à travers un tableau de la manière de programmation fonctionnelle en JavaScript:

1. Il suffit de parcourir un tableau

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

Remarque: Array.prototype.forEach () n'est pas une manière fonctionnelle à proprement parler, car la fonction qu'il prend comme paramètre d'entrée n'est pas censée renvoyer une valeur, qui ne peut donc pas être considérée comme une fonction pure.

2. Vérifiez si l'un des éléments d'un tableau réussit 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. Transformez-vous en un nouveau tableau

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

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

Remarque: La méthode map () crée un nouveau tableau avec les résultats de l'appel d'une fonction fournie sur chaque élément du tableau appelant.

4. Résumez une propriété particulière et calculez sa moyenne

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. Créez un nouveau tableau basé sur l'original mais sans le modifier

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. Comptez le nombre de chaque catégorie

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. Récupérer un sous-ensemble d'un tableau en fonction de critères particuliers

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

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

Remarque: La méthode filter () crée un nouveau tableau avec tous les éléments qui réussissent le test implémenté par la fonction fournie.

8. Trier un tableau

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

entrez la description de l'image ici

9. Trouver un élément dans un tableau

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

entrez la description de l'image ici

La méthode Array.prototype.find () renvoie la valeur du premier élément du tableau qui satisfait la fonction de test fournie.

Références

Yuci
la source
30

Il existe un moyen de le faire lorsque vous avez très peu de portée implicite dans votre boucle et de supprimer les variables supplémentaires.

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

Ou si vous voulez vraiment obtenir l'id et avoir une forboucle vraiment classique :

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
}

Les navigateurs modernes toutes les méthodes iterator de soutien forEach, map, reduce, filteret une foule d'autres méthodes sur le prototype Array .

Gabriel
la source
3
Notez que certains interprètes (par exemple V8) mettent automatiquement en cache la longueur du tableau si le code est appelé suffisamment de fois et qu'il détecte que la longueur n'est pas modifiée par la boucle.
Phrogz
Merci pour l'info @Phrogz, il est vrai qu'il y a beaucoup d'optimisations que la VM peut faire, mais comme les anciens navigateurs ne l'ont pas, il serait toujours préférable de l'optimiser car elle est si bon marché.
Gabriel
1
@Gabriel: Pourquoi? Veuillez donner des exemples concrets montrant que la non mise en cache de la longueur est en fait un goulot d'étranglement des performances. Je suis l'approche «l'optimisation prématurée est la racine de tout mal». Je vais corriger cette boucle qui pose réellement un problème une fois que je la rencontre ...
Stijn de Witt
1
@StijndeWitt imo c'est juste une question stylistique. Honnêtement, je n'utilise même plus de boucles au lieu de compter sur le soulignement pour des choses comme _.each, _.map etc. pour faire ces choses. Quand j'ai écrit des boucles comme celle-ci, j'ai mis en cache la longueur principalement pour que toutes mes déclarations de variables soient au même endroit, en haut de ma fonction. Suivre mes conseils à cet égard est sans conséquence pour toute application réelle. L'optimisation prématurée est super mauvaise, mais si l'optimisation résulte de décisions stylistiques, je ne pense pas que cela compte vraiment.
Gabriel
1
@Gabriel Je crois que JavaScript prend déjà en charge la fonction de carte sur les tableaux, pas besoin d'introduire une bibliothèque supplémentaire pour cela.
Noz
28

Il existe différentes façons de parcourir le tableau en JavaScript.

Boucle générique:

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

ES5 forEach:

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

Jetez un oeil à cela pour des informations détaillées ou vous pouvez également vérifier MDN pour boucler à travers un tableau en JavaScript et en utilisant jQuery vérifier jQuery pour chacun .

RizN81
la source
27

Je recommande vivement d'utiliser la bibliothèque underscore.js . Il vous offre diverses fonctions que vous pouvez utiliser pour parcourir les tableaux / collections.

Par exemple:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...
Andrew Thomson
la source
7
Pour les nouveaux découvreurs de cette question, je voudrais juste souligner Lo-Dash , un successeur spirituel de Underscore qui l'améliore à bien des égards.
Mark Reed
3
Pourquoi utiliser underscoresi ECMA-262 a été ajouté la forEachméthor. Le code natif est toujours meilleur.
Walter Chapilliquen - wZVanG
27

Boucle de tableau:

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

Boucle d'objet:

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

Oui , vous pouvez faire la même chose en JavaScript en utilisant une boucle, mais sans s'y limiter , il existe de nombreuses façons de faire une boucle sur des tableaux en JavaScript. Imaginez que vous avez ce tableau ci-dessous et que vous souhaitez faire une boucle dessus:

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

Ce sont les solutions:

1) Pour la boucle

Une forboucle est un moyen courant de parcourir les tableaux en JavaScript, mais n'est pas considérée comme la solution la plus rapide pour les grands tableaux:

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

2) En boucle

Une boucle while est considérée comme le moyen le plus rapide de parcourir de longs tableaux, mais elle est généralement moins utilisée dans le code JavaScript:

let i=0;

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

3) Faites pendant que
A do whilefait la même chose whilequ'avec une différence de syntaxe comme ci-dessous:

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

Ce sont les principales façons de faire des boucles JavaScript, mais il existe plusieurs autres façons de le faire.

Nous utilisons également une for inboucle pour faire une boucle sur des objets en JavaScript.

Regardez aussi les map(), filter(), reduce(), etc. fonctions sur un tableau en JavaScript. Ils peuvent faire les choses beaucoup plus rapidement et mieux que d'utiliser whileet for.

C'est un bon article si vous souhaitez en savoir plus sur les fonctions asynchrones sur les tableaux en JavaScript.

La programmation fonctionnelle a fait sensation dans le monde du développement ces jours-ci. Et pour cause: les techniques fonctionnelles peuvent vous aider à écrire du code déclaratif plus facile à comprendre en un coup d'œil, à refactoriser et à tester.

L'une des pierres angulaires de la programmation fonctionnelle est son utilisation spéciale des listes et des opérations de liste. Et ces choses sont exactement ce qu'elles sont: des tableaux de choses et ce que vous leur faites. Mais l'état d'esprit fonctionnel les traite un peu différemment que vous ne le pensez.

Cet article examinera de près ce que j'aime appeler les «grandes trois» opérations de liste: mapper, filtrer et réduire. Envelopper votre tête autour de ces trois fonctions est une étape importante vers la possibilité d'écrire du code fonctionnel propre et ouvre les portes aux techniques extrêmement puissantes de programmation fonctionnelle et réactive.

Cela signifie également que vous n'aurez plus jamais à écrire une boucle for.

En savoir plus >> ici :

Alireza
la source
Existe-t-il vraiment une différence de performances avant une boucle for et une boucle while lors de l'itération à travers un tableau? J'avais l'impression que les différences étaient principalement syntaxiques
karité
24

Si quelqu'un s'intéresse aux performances des multiples mécanismes disponibles pour les itérations de tableau, j'ai préparé les tests JSPerf suivants:

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

Résultats de performance

Résultats:

L' for()itérateur traditionnel est de loin la méthode la plus rapide, surtout lorsqu'il est utilisé avec la longueur de tableau mise en cache .

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

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

Les Array.prototype.forEach()et les Array.prototype.map()méthodes sont les plus lents approximations, probablement en raison de la surcharge d'appel de fonction .

colxi
la source
est une meilleure utilisation i = i +1au lieu dei++
DarckBlezzer
2
Pourrait être amélioré: veuillez utiliser: ++ i au lieu de i ++, cela évitera un objet temporaire. Cela réduit donc l'utilisation de la mémoire et le temps processeur (aucune allocation requise)!
PowerStat
@PowerStat pouvez-vous fournir un lien ou une référence à ce sujet? Je n'en ai jamais entendu parler, ça a l'air intéressant ...
colxi
1
@colxi Pour des choses aussi intéressantes, vous devriez lire les trucs C ++ hardcore de Herb Sutter et Scott Meyers. La chose ++ i vs i ++ est tirée du livre: Exceptional C ++: 47 Engineering Puzzles, Programming Problems, and Solutions - je pense que vous pouvez également le trouver sur gotw.ca, mais cela peut être prouvé pour tous les langages de programmation.
PowerStat
21

Si vous utilisez la bibliothèque jQuery, pensez à utiliser http://api.jquery.com/jQuery.each/

De la documentation:

jQuery.each( collection, callback(indexInArray, valueOfElement) )

Renvoie: Object

Description: une fonction d'itérateur générique, qui peut être utilisée pour itérer de manière transparente sur les objets et les tableaux. Les tableaux et les objets de type tableau avec une propriété length (comme un objet arguments d'une fonction) sont itérés par un index numérique, de 0 à length-1. D'autres objets sont itérés via leurs propriétés nommées.

La $.each()fonction n'est pas la même que celle $(selector).each()qui est utilisée pour itérer, exclusivement, sur un objet jQuery. La $.each() fonction peut être utilisée pour itérer sur n'importe quelle collection, qu'il s'agisse d'une carte (objet JavaScript) ou d'un tableau. Dans le cas d'un tableau, le rappel reçoit à chaque fois un index de tableau et une valeur de tableau correspondante. (La valeur est également accessible via le thismot clé, mais Javascript encapsulera toujours la thisvaleur en tant que Objectmême s'il s'agit d'une simple chaîne ou d'une valeur numérique.) La méthode renvoie son premier argument, l'objet qui a été itéré.

justingordon
la source
9
jQuery pour tout?
Exception
6
D'accord avec exception. Ne sous-estimez pas l'impact des dépendances supplémentaires. Je déconseille cela, sauf dans le code qui utilise déjà fortement jQuery de toute façon.
Stijn de Witt
2
Mise à jour: De nos jours, vous pouvez utiliser Array.forEach pour obtenir à peu près le même effet avec les tableaux natifs.
Stijn de Witt
21

Je n'ai pas encore vu cette variation, que j'aime personnellement le mieux:

Étant donné un tableau:

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

Vous pouvez faire une boucle dessus sans jamais accéder à la propriété 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);
}

Voir ce JsFiddle démontrant que: http://jsfiddle.net/prvzk/

Cela ne fonctionne que pour les tableaux qui ne sont pas rares. Cela signifie qu'il existe en fait une valeur à chaque index du tableau. Cependant, j'ai trouvé que dans la pratique, j'utilise rarement des tableaux clairsemés en JavaScript ... Dans de tels cas, il est généralement beaucoup plus facile d'utiliser un objet comme carte / table de hachage. Si vous avez un tableau clairsemé et que vous souhaitez boucler sur 0 .. longueur-1, vous avez besoin de la construction for (var i = 0; i <someArray.length; ++ i), mais vous avez toujours besoin d'un ifà l'intérieur de la boucle pour vérifier si l'élément de l'index en cours est réellement défini.

De plus, comme CMS le mentionne dans un commentaire ci-dessous, vous ne pouvez l'utiliser que sur des tableaux qui ne contiennent aucune valeur fausse. Le tableau de chaînes de l'exemple fonctionne, mais si vous avez des chaînes vides, ou des nombres qui sont 0 ou NaN, etc., la boucle se rompra prématurément. Encore une fois dans la pratique, ce n'est presque jamais un problème pour moi, mais c'est quelque chose à garder à l'esprit, ce qui en fait une boucle à penser avant de l'utiliser ... Cela peut le disqualifier pour certaines personnes :)

Ce que j'aime dans cette boucle c'est:

  • C'est court pour écrire
  • Pas besoin d'accéder (sans parler du cache) à la propriété length
  • L'élément auquel accéder est automatiquement défini dans le corps de la boucle sous le nom que vous choisissez.
  • Se combine très naturellement avec array.push et array.splice pour utiliser des tableaux comme des listes / piles

La raison pour laquelle cela fonctionne est que la spécification du tableau stipule que lorsque vous lisez un élément à partir d'un index> = la longueur du tableau, il retournera indéfini. Lorsque vous écrivez à un tel emplacement, cela mettra à jour la longueur.

Pour moi, cette construction émule le plus fidèlement la syntaxe Java 5 que j'aime:

for (String item : someArray) {
}

... avec l'avantage supplémentaire de connaître également l'index actuel dans la boucle

Stijn de Witt
la source
14
Notez que cette approche la boucle s'arrêtera dès qu'il trouve une valeur Falsey , comme une chaîne vide, 0, false, NaN, nullou undefined, avant même iatteint la longueur, par exemple: jsfiddle.net/prvzk/1
CMS
3
La condition de boucle pourrait être (item=someArray[i]) !== undefined.
daniel1426
18

Il existe une méthode pour parcourir uniquement les propriétés de ses propres objets, à l'exclusion de celles du prototype:

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

mais il itérera toujours sur les propriétés personnalisées.

En JavaScript, toute propriété personnalisée peut être affectée à n'importe quel objet, y compris un tableau.

Si l'on veut parcourir un tableau épars, for (var i = 0; i < array.length; i++) if (i in array)ou array.forEachavec es5shimdoit être utilisé.

kirilloïde
la source
Et que diriez-vous d'utiliser for (var i in array) if (++i)?
Daniel Sokolowski
15

Il existe plusieurs façons de le faire en JavaScript. Les deux premiers exemples sont des exemples JavaScript. Le troisième utilise une bibliothèque JavaScript, c'est-à-dire que jQuery utilise la .each()fonction.

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>

Shubham Khatri
la source
for...indevrait être évité pour les objets de type tableau
brk
15

La manière la plus élégante et la plus rapide

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

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


Modifié (parce que j'avais tort)


Comparaison des méthodes pour parcourir un tableau de 100 000 éléments et effectuer à chaque fois une opération minimale avec la nouvelle valeur.

Préparation:

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

Tests:

<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>
molokoloco
la source
Cette boucle ne semble pas suivre l'ordre des éléments du tableau.
Deniz Ozger
Mon test était faux. C'est correct, montrant toutes les boucles maintenant. jsperf.com/native-loop-performance/16
molokoloco
@bergi a raison. Cette boucle efface le tableau lors de sa boucle. Pas ce que vous voulez dans la plupart des cas.
Stijn de Witt
4
pauses sur les articles falsey.
njzk2
12

L'approche optimisée consiste à mettre en cache la longueur du tableau et à utiliser un modèle var unique initialisant toutes les variables avec un seul mot clé var.

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

Si l'ordre d'itération n'a pas d'importance que vous devriez essayer la boucle inversée, c'est plus rapide car cela réduit les tests de condition de surcharge et la décrémentation est dans une instruction:

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

ou mieux et plus propre à utiliser en boucle:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // do something with fruits[i]
}
Zaheer Ahmed
la source
12

En JavaScript, il existe de nombreuses solutions pour boucler un tableau.

Le code ci-dessous est populaire

/** 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()

Alongkorn Chetasumon
la source
12

Si vous souhaitez utiliser jQuery, il a un bel exemple dans sa documentation:

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

À mon avis, la meilleure façon est d'utiliser la fonction Array.forEach. Si vous ne pouvez pas l'utiliser, je vous suggère d'obtenir le polyfill de MDN. Pour le rendre disponible, c'est certainement le moyen le plus sûr d'itérer sur un tableau en JavaScript.

Array.prototype.forEach ()

Donc, comme d'autres l'ont suggéré, c'est presque toujours ce que vous voulez:

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

Cela garantit que tout ce dont vous avez besoin dans la portée du traitement du tableau reste dans cette portée, et que vous ne traitez que les valeurs du tableau, pas les propriétés de l'objet et les autres membres, ce qui est ce que for .. cas.

Utilisation d'un style C normal for boucle fonctionne dans la plupart des cas. Il est juste important de se rappeler que tout dans la boucle partage sa portée avec le reste de votre programme, le {} ne crée pas de nouvelle portée.

Par conséquent:

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

affichera "11" - qui peut ou non être ce que vous voulez.

Un exemple de jsFiddle fonctionnel: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/

Espen
la source
10

Ce n'est pas 100% identique, mais similaire:

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

Muhammad Alvin
la source
1
Il semble que cela se heurterait à des problèmes similaires à ceux des autres dans les utilisations avec un objet tableau, dans la mesure où les variables membres du prototype seraient également capturées par le for dans.
Kzqai
9

Par exemple, j'ai utilisé dans une console Firefox:

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})
victorq10
la source
9
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

Beaucoup plus propre ...

staticd
la source
Ce n'est pas très propre par rapport à z.forEach(j => console.log(j));.
Sapphire_Brick
9

Réponse courte: oui. Vous pouvez faire cela:

var myArray = ["element1", "element2", "element3", "element4"];

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

Dans une console de navigateur, vous pouvez voir quelque chose comme "element1", "element2", etc., imprimé.

Juanjo Salvador
la source
9

Vous pouvez soit utiliser Array.prototype.forEach(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach((item, index)=>{
   //Some code...
});

Ou Array.prototype.map(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.map((item, index)=>{
   //Some code...
});

Ou le jquery ou pour les chemins de boucle mentionnés précédemment.

Sapphire_Brick
la source