Question Boucle à travers un tableau en JavaScript


En Java, vous pouvez utiliser un for boucle pour parcourir les objets dans un tableau comme suit:

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

Pouvez-vous faire la même chose en JavaScript?


2415
2018-06-10 00:04


origine


Réponses:


Utiliser un séquentiel for boucle:

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

@zipcodeman suggère l'utilisation de for...in déclaration, mais pour les tableaux d'itération for-in devrait être évitée, cette déclaration est destinée à énumérer propriétés de l'objet.

Il ne devrait pas être utilisé pour les objets de type tableau parce que:

  • L'ordre d'itération n'est pas garanti, les index de tableau peuvent ne 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 qu'il peut vous donner beaucoup de problèmes, par exemple, si vous étendez la Array.prototype objet 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) {
  alert(array[i]);
}

Le code ci-dessus alerte, "a", "b", "c" et "foo!".

Cela est particulièrement un problème si vous utilisez une bibliothèque qui repose fortement sur l'augmentation de prototypes natifs (comme MooTools par exemple).

le for-in déclaration que je l'ai déjà dit est là pour énumérer propriétés de l'objet, 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...
    alert("prop: " + prop + " value: " + obj[prop])
  }
}

Dans l'exemple ci-dessus, le hasOwnProperty méthode vous permet d'énumérer seulement propres propriétés, c'est ça, seulement les propriétés physiques de l'objet, pas de propriétés héritées.

Je vous recommande de lire l'article suivant:


3050
2018-06-10 00:07



Oui, mais seulement si votre implémentation inclut le for...of fonctionnalité introduite dans ECMAScript 2015 (la version "Harmony").

Cela fonctionne comme ceci:

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

Ou mieux encore, puisque ECMAScript 2015 fournit également des variables de portée let et const:

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

De nombreux développeurs JavaScript travaillent toujours dans un environnement qui n'existe pas encore, en particulier si vous écrivez du code pour fonctionner dans des navigateurs Web, où les développeurs de sites ne peuvent souvent pas savoir quel navigateur / version leurs clients vont utiliser.

Si vous pouvez supposer que l'interpréteur JavaScript est conforme à la précédent édition de la spécification ECMAScript (qui exclut, par exemple, les versions d'Internet Explorer avant 9), vous pouvez utiliser forEach mé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 ...
} );

Mais si même cela est trop à assumer, et que vous voulez quelque chose qui fonctionne dans tout versions de JavaScript, alors vous devez utiliser une boucle de comptage explicite. La version la plus sûre, qui gère correctement les tableaux clairsemés, ressemble à ceci:

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

Affectation de la valeur de longueur à la variable locale (par opposition à l'inclusion de myStringArray.length expression dans la condition de boucle) peut faire une différence significative dans les performances, car il saute une recherche de propriété à chaque fois; en utilisant Rhino sur ma machine, l'accélération est de 43%.

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

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

le for...in la syntaxe mentionnée par d'autres est pour faire une boucle sur les propriétés d'un objet; depuis un tableau en JavaScript est juste un objet avec des noms de propriété numériques (et un automatiquement mis à jour lengthpropriété), vous pouvez théoriquement faire une boucle sur un tableau avec celui-ci. Mais le problème est qu'il ne se limite pas aux valeurs de propriété numériques (souvenez-vous que même les méthodes ne sont en fait que des propriétés dont la valeur est une fermeture), et qu'il ne parcourt pas les valeurs numériques. Par conséquent, la for...in la syntaxe devrait ne pas être utilisé pour faire une boucle dans les tableaux.


868
2018-04-16 02:03



Vous pouvez utiliser map, qui est une technique de programmation fonctionnelle qui est également disponible dans d'autres langues 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.map est un autre tableau, donc vous pouvez l'utiliser comme ceci:

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

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

Vous n'avez pas besoin d'écrire la fonction en ligne. Cela pourrait être une fonction séparée.

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 n'obtenez pas le new_list.


391
2018-06-10 00:09



En JavaScript, il n'est pas conseillé de faire une boucle dans un tableau avec une boucle for-in, mais il est préférable d'utiliser une boucle for comme:

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, lire mon post sur le sujet.


102
2017-12-07 07:24



pour (var s de myStringArray) {

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

La plupart des autres réponses sont justes, mais elles ne mentionnent pas (au moment de la rédaction) Script ECMA 6 2015 apporte un nouveau mécanisme pour faire l'itération, le for..of boucle.

Cette nouvelle syntaxe est la façon la plus élégante d'itérer un tableau en javascript (tant que vous n'avez pas besoin de l'index d'itération), mais il n'est pas encore largement supporté par les navigateurs.

Il fonctionne actuellement avec Firefox 13+, Chrome 37+ et 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 aussi sur Node (je l'ai testé sur la version 0.12.0).

Itérer un tableau

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

Itérer 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érer 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 boucles

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

}


92
2017-08-11 15:54



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

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

Mozilla Labs a publié les algorithmes eux et WebKit les deux utilisent, de sorte que vous pouvez les ajouter vous-même.

filtre retourne un tableau d'éléments qui satisfont certaines conditions ou tests.

chaque renvoie true si tous les membres du groupe réussissent le test.

certains renvoie vrai si n'importe quel passage le test.

pour chaque exécute une fonction sur chaque membre du groupe et ne renvoie rien.

carte est comme forEach, mais renvoie 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 optionnel, qui est un objet dont vous voulez imposer la portée aux membres du tableau lorsqu'ils parcourent la fonction.

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

Indice de et lastIndexOf trouver 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;
})();

81
2018-06-10 02:43



Utilisez la boucle while ...

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

logs: '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]);
}

logs: 'trois', 'deux', 'un'

Ou le classique for boucle

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

logs: 'un', 'deux', 'trois'

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


62
2018-01-05 09:15



Intro

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

Alors qu'ils ont tous leurs propres idiosyncrasies linguistiques, chacune de ces langues partagent plusieurs des mêmes concepts de base. De tels concepts incluent des procédures / fonctions, IF-statements, FOR-loops, et WHILE-boucles.


Une traditionnelle for-boucle

Une traditionnelle for La boucle a trois composants:

  1. L'initialisation: exécuté avant que le bloc de regard est exécuté la première fois
  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. La suite: effectué à chaque fois après que le bloc de boucle est exécuté

Ces trois composants sont séparés les uns des autres par un ; symbole. Le contenu de chacune de ces trois composantes est facultatif, ce qui signifie que ce qui suit est le plus minimal for boucle 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 for-loop pour l'empêcher 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 l'arrière-pensée est utilisée pour incrémenter l'index:

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

En utilisant un traditionnel for boucle pour faire une boucle dans un tableau

La façon traditionnelle de faire une boucle dans 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 faites ceci:

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

Il y a, cependant, de nombreuses variations 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 le cas d'utilisation spécifique que vous mettez en œuvre.

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


UNE while boucle

Une alternative à un for la boucle est un whileboucle. Pour faire une boucle dans un tableau, vous pouvez faire ceci:

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

Comme traditionnel for boucles, while Les boucles sont supportées par les plus vieux navigateurs.

Notez également que chaque boucle while peut être réécrite en tant que for boucle. Par exemple, le while boucle hereabove se comporte exactement de la même manière que cette for-boucle:

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

For...in et for...of

En JavaScript, vous pouvez aussi faire ceci:

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

Cela doit être utilisé avec précaution, car il ne se comporte pas comme un traditionnel for boucle dans tous les cas, et il y a des effets secondaires potentiels qui doivent être considérés. Voir Pourquoi utiliser "pour ... dans" avec itération de tableau une mauvaise idée? pour plus de détails.

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

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
}

En outre, vous devez considérer qu'aucune version d'Internet Explorer ne prend en charge for...of (Edge 12+ fait) et que for...in né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 que par Internet Explorer 9 et versions ultérieures.


Bibliothèques

Enfin, de nombreuses bibliothèques de services publics ont aussi leur propre foreach variation. AFAIK, les trois plus populaires sont ceux-ci:

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

48
2018-02-29 18:56