Comment puis-je parcourir toutes les entrées d'un tableau en utilisant JavaScript?
Je pensais que c'était quelque chose comme ça:
forEach(instance in theArray)
Où theArray
est mon tableau, mais cela semble être incorrect.
TL; DR
for-in
_ sauf si vous l'utilisez avec des sauvegardes ou si vous êtes au moins conscient de la raison pour laquelle il pourrait vous mordre.Vos meilleurs paris sont généralement
Mais il y alotsplus à explorer, lisez la suite ...
JavaScript possède une sémantique puissante pour la boucle dans les tableaux et les objets semblables à des tableaux. J'ai divisé la réponse en deux parties: Options pour les tableaux authentiques et options pour les éléments qui ne sont que des tableaux - comme , tels que l'objet arguments
, d'autres objets itérables (ES2015 +), DOM collections, etc.
Je noterai rapidement que vous pouvez utiliser les options ES2015 maintenant , même sur les moteurs ES5, en transpiler ES2015 à ES5. Recherche de "ES2015 transpiling"/"ES6 transpiling" pour plus ...
Ok, regardons nos options:
Vous avez trois options dans ECMAScript 5 ("ES5"), la version la plus largement prise en charge pour le moment, et deux autres ajoutées dans ECMAScript 2015 ("ES2015", "ES6") :
forEach
et connexes (ES5 +)for
for-in
_ correctement for-of
_ (utilisez implicitement un itérateur) (ES2015 +)Détails:
forEach
et connexeDans tout environnement vaguement moderne (donc pas IE8) où vous avez accès aux fonctionnalités Array
ajoutées par ES5 (directement ou à l'aide de polyfill), vous pouvez utiliser forEach
( spec
| MDN
):
_var a = ["a", "b", "c"];
a.forEach(function(entry) {
console.log(entry);
});
_
forEach
accepte une fonction de rappel et, éventuellement, une valeur à utiliser en tant que this
lors de l'appel de ce rappel (non utilisé ci-dessus). Le rappel est appelé pour chaque entrée du tableau, dans l'ordre, en ignorant les entrées inexistantes dans les tableaux fragmentés. Bien que je n’ai utilisé qu’un seul argument ci-dessus, le rappel est appelé avec trois: la valeur de chaque entrée, l’index de cette entrée et une référence au tableau sur lequel vous effectuez une itération (au cas où votre fonction ne l’aurait pas déjà à portée de main) ).
À moins que vous ne preniez en charge des navigateurs obsolètes tels que IE8 (dont NetApps affiche une part de marché légèrement supérieure à 4% à la date de rédaction de ce rapport en septembre 2016), vous pouvez utiliser forEach
dans une page Web à usage général sans cale. Si vous devez prendre en charge des navigateurs obsolètes, le calage/le remplissage de forEach
se fait facilement (recherchez "es5 shim" pour plusieurs options).
forEach
a l'avantage de ne pas avoir à déclarer les variables d'indexation et de valeur dans la portée qui les contient, car elles sont fournies en tant qu'arguments de la fonction d'itération, et sont donc parfaitement adaptées à cette itération.
Si le coût d'exécution d'un appel de fonction pour chaque entrée de tableau vous inquiète, ne le soyez pas; détails .
De plus, forEach
est la fonction "En boucle entre eux", mais ES5 a défini plusieurs autres fonctions utiles "Parcourez le tableau et effectuez des actions", notamment:
every
(arrête de boucler la première fois que le rappel retourne false
ou quelque chose de similaire)some
(arrête de boucler la première fois que le rappel retourne true
ou quelque chose de vrai)filter
(crée un nouveau tableau comprenant des éléments pour lesquels la fonction de filtrage renvoie true
et en omettant ceux pour lesquels il renvoie false
)map
(crée un nouveau tableau à partir des valeurs renvoyées par le rappel)reduce
(construit une valeur en appelant plusieurs fois le rappel, en transmettant les valeurs précédentes; voir la spécification pour les détails; utile pour faire la somme du contenu d'un tableau et pour bien d'autres choses)reduceRight
(comme reduce
, mais fonctionne par ordre décroissant plutôt que croissant)for
Parfois, les anciennes méthodes sont les meilleures:
_var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
console.log(a[index]);
}
_
Si la longueur du tableau ne change pas pendant la boucle et que le code est sensible aux performances (improbable), une version un peu plus compliquée prenant la longueur à l’avant pourrait bien être un minuscule bit plus rapide:
_var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
console.log(a[index]);
}
_
Et/ou compte à rebours:
_var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
console.log(a[index]);
}
_
Mais avec les moteurs JavaScript modernes, il est rare que vous ayez besoin de ce dernier coup de pouce.
Dans ES2015 et versions ultérieures, vous pouvez associer vos variables d'index et de valeur à la boucle for
:
_let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
let value = a[index];
console.log(index, value);
}
//console.log(index); // would cause "ReferenceError: index is not defined"
//console.log(value); // would cause "ReferenceError: value is not defined"
_
_let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
let value = a[index];
console.log(index, value);
}
try {
console.log(index);
} catch (e) {
console.error(e); // "ReferenceError: index is not defined"
}
try {
console.log(value);
} catch (e) {
console.error(e); // "ReferenceError: value is not defined"
}
_
Et lorsque vous faites cela, non seulement value
, mais aussi index
est recréé pour chaque itération de boucle, ce qui signifie que les fermetures créées dans le corps de la boucle gardent une référence au index
(et value
) créé pour cette itération spécifique:
_let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
divs[index].addEventListener('click', e => {
console.log("Index is: " + index);
});
}
_
_let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
divs[index].addEventListener('click', e => {
console.log("Index is: " + index);
});
}
_
_<div>zero</div>
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>
_
Si vous aviez cinq divs, vous obtiendrez "Index is: 0" si vous avez cliqué sur le premier et "Index is: 4" si vous avez cliqué sur le dernier. Cela fonctionnenotsi vous utilisez var
au lieu de let
.
for-in
_ correctement Vous obtiendrez des personnes qui vous diront d'utiliser _for-in
_, mais ce n'est pas ce que _for-in
_ est pour . _for-in
_ parcourt les propriétés énumérables d'un objet et non les index d'un tableau.La commande n'est pas garantie, pas même dans ES2015 (ES6). ES2015 + définit un ordre pour les propriétés d'objet (via [[OwnPropertyKeys]]
, [[Enumerate]]
et les choses qui les utilisent comme Object.getOwnPropertyKeys
), maisne/ne définit pas que _for-in
_ suivra cet ordre. (Détails dans cette autre réponse .)
Les seuls cas d'utilisation réels de _for-in
_ sur un tableau sont les suivants:
En regardant seulement ce premier exemple: Vous pouvez utiliser _for-in
_ pour visiter ces éléments de tableau sparais si vous utilisez les sauvegardes appropriées:
_// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
if (a.hasOwnProperty(key) && // These checks are
/^0$|^[1-9]\d*$/.test(key) && // explained
key <= 4294967294 // below
) {
console.log(a[key]);
}
}
_
Notez les trois contrôles:
Que l'objet possède sa propriété propre portant ce nom (et non un héritage de son prototype), et
Que la clé est composée uniquement de chiffres décimaux (par exemple, forme de chaîne normale, pas de notation scientifique), et
Que la valeur de la clé lorsque contraint à un nombre est <= 2 ^ 32 - 2 (qui est 4,294,967,294). D'où vient ce nombre? Cela fait partie de la définition d'un indice de tableau dans la spécification . Les autres nombres (non-entiers, nombres négatifs, nombres supérieurs à 2 ^ 32 - 2) ne sont pas des index de tableau. La raison pour laquelle il s’agit de 2 ^ 32 -2est que la plus grande valeur de l’index est inférieure à 2 ^ 32 -1, qui est la valeur maximale d’un tableau length
peut avoir. (Par exemple, la longueur d'un tableau correspond à un entier non signé de 32 bits.) (Merci à RobG pour avoir souligné dans un commentaire sur mon blog que mon test précédent n'était pas tout à fait correct .)
Vous ne feriez pas cela dans le code en ligne, bien sûr. Vous écririez une fonction utilitaire. Peut-être:
_// Utility function for antiquated environments without `forEach`
var hasOwn = Object.prototype.hasOwnProperty;
var rexNum = /^0$|^[1-9]\d*$/;
function sparseEach(array, callback, thisArg) {
var index;
for (var key in array) {
index = +key;
if (hasOwn.call(a, key) &&
rexNum.test(key) &&
index <= 4294967294
) {
callback.call(thisArg, array[key], index, array);
}
}
}
var a = [];
a[5] = "five";
a[10] = "ten";
a[100000] = "one hundred thousand";
a.b = "bee";
sparseEach(a, function(value, index) {
console.log("Value at " + index + " is " + value);
});
_
for-of
_ (utilisez implicitement un itérateur) (ES2015 +)ES2015 ajoute des itérateurs à JavaScript. Le moyen le plus simple d'utiliser des itérateurs est la nouvelle instruction _for-of
_. Cela ressemble à ceci:
_const a = ["a", "b", "c"];
for (const val of a) {
console.log(val);
}
_
Sous les couvertures, cela obtient un itérateur du tableau et le parcourt, en obtenant les valeurs. Cela n'a pas le problème que l'utilisation de _for-in
_ a, car il utilise un itérateur défini par l'objet (le tableau), et les tableaux définissent que leurs itérateurs itèrent à travers leurs entrées (pas leurs propriétés). Contrairement à _for-in
_ dans ES5, l'ordre dans lequel les entrées sont visitées est l'ordre numérique de leurs index.
Parfois, vous pouvez utiliser un itérateur explicitement . Vous pouvez le faire aussi, même si c'est beaucoup plus encombrant que _for-of
_. Cela ressemble à ceci:
_const a = ["a", "b", "c"];
const it = a.values();
let entry;
while (!(entry = it.next()).done) {
console.log(entry.value);
}
_
L'itérateur est un objet correspondant à la définition d'Iterator dans la spécification. Sa méthode next
renvoie un nouvel objet de résultat à chaque appel. L'objet de résultat a une propriété, done
, nous indiquant si c'est fait, et une propriété value
avec la valeur de cette itération. (done
est optionnel si ce serait false
, value
est optionnel s'il était undefined
.)
La signification de value
varie selon l’itérateur; Les tableaux prennent en charge (au moins) trois fonctions renvoyant des itérateurs:
values()
: C'est celui que j'ai utilisé ci-dessus. Il renvoie un itérateur où chaque value
est l'entrée du tableau pour cette itération (_"a"
_, _"b"
_ et _"c"
_ dans l'exemple précédent).keys()
: Retourne un itérateur où chaque value
est la clé de cette itération (donc pour notre a
ci-dessus, ce serait _"0"
_, puis _"1"
_, puis _"2"
_).entries()
: renvoie un itérateur où chaque value
est un tableau de la forme _[key, value]
_ pour cette itération.En plus des tableaux réels, il existe également des objets de type tableau dotés d'une propriété length
et de propriétés portant des noms numériques: instances NodeList
, objet arguments
, etc. Comment pouvons-nous parcourir leur contenu?
Au moins certaines, et peut-être même la plupart, voire toutes les approches de tableau ci-dessus s'appliquent également aux objets de type tableau:
Utilisez forEach
et connexes (ES5 +)
Les différentes fonctions de _Array.prototype
_ sont "intentionnellement génériques" et peuvent généralement être utilisées sur des objets de type tableau via Function#call
ou Function#apply
. (Voir l'avertissement relatif aux objets fournis par l'hôte à la fin de cette réponse, mais il s'agit d'un problème rare.)
Supposons que vous souhaitiez utiliser forEach
sur la propriété Node
's childNodes
. Tu ferais ça:
_Array.prototype.forEach.call(node.childNodes, function(child) {
// Do something with `child`
});
_
Si vous envisagez beaucoup de choses, vous pouvez extraire une copie de la référence de la fonction dans une variable pour la réutiliser, par exemple:
_// (This is all presumably in some scoping function)
var forEach = Array.prototype.forEach;
// Then later...
forEach.call(node.childNodes, function(child) {
// Do something with `child`
});
_
Utilisez une simple boucle for
De toute évidence, une simple boucle for
s'applique aux objets de type tableau.
Utilisez _for-in
_ correctement
_for-in
_ avec les mêmes protections que pour un tableau devrait également fonctionner avec des objets de type tableau; l'avertissement pour les objets fournis par l'hôte au n ° 1 ci-dessus peut s'appliquer.
Utilisez _for-of
_ (utilisez implicitement un itérateur) (ES2015 +)
_for-of
_ utilisera l'itérateur fourni par l'objet (le cas échéant); nous devrons voir comment cela joue avec les divers objets de type tableau, en particulier ceux fournis par l'hôte. Par exemple, la spécification pour NodeList
de querySelectorAll
a été mise à jour pour prendre en charge l'itération. La spécification pour le HTMLCollection
de getElementsByTagName
ne l’était pas.
Utiliser explicitement un itérateur (ES2015 +)
Voir n ° 4, nous devrons voir comment les itérateurs jouent.
D'autres fois, vous voudrez peut-être convertir un objet semblable à un tableau en un vrai tableau. Faire cela est étonnamment facile:
Utilisez la méthode slice
des tableaux
Nous pouvons utiliser la méthode de tableaux slice
, qui, comme les autres méthodes mentionnées ci-dessus, est "intentionnellement générique" et peut donc être utilisée avec des objets de type tableau, comme ceci:
_var trueArray = Array.prototype.slice.call(arrayLikeObject);
_
Ainsi, par exemple, si nous voulons convertir un NodeList
en un tableau vrai, nous pourrions faire ceci:
_var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
_
Voir la mise en garde concernant les objets fournis par l'hôte ci-dessous. En particulier, notez que cela échouera dans IE8 et les versions antérieures, ce qui ne vous permettra pas d'utiliser des objets fournis par l'hôte sous la forme this
comme cela.
Utiliser répandre la syntaxe (_...
_)
Il est également possible d'utiliser la syntaxe spread de ES2015 avec des moteurs JavaScript prenant en charge cette fonctionnalité:
_var trueArray = [...iterableObject];
_
Ainsi, par exemple, si nous voulons convertir un NodeList
en un vrai tableau, avec une syntaxe étendue, cela devient assez succinct:
_var divs = [...document.querySelectorAll("div")];
_
Utilisez _Array.from
_(spec) | (MDN)
_Array.from
_ (ES2015 +, mais polyfilled facilement) crée un tableau à partir d'un objet de type tableau, en passant éventuellement les entrées à travers une fonction de mappage. Alors:
_var divs = Array.from(document.querySelectorAll("div"));
_
Ou si vous voulez obtenir un tableau des noms de balises des éléments avec une classe donnée, utilisez la fonction de mappage:
_// Arrow function (ES2015):
var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
// Standard function (since `Array.from` can be shimmed):
var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
return element.tagName;
});
_
Si vous utilisez des fonctions _Array.prototype
_ avec des objets de type tableau fournis par l'hôte (listes DOM et autres éléments fournis par le navigateur plutôt que par le moteur JavaScript), vous devez vous assurer de: Testez dans vos environnements cibles pour vous assurer que l'objet fourni par l'hôte se comporte correctement.La plupart se comportent correctement(maintenant), mais il est important de tester. La raison en est que la plupart des méthodes _Array.prototype
_ que vous voudrez probablement utiliser dépendent de l'objet fourni par l'hôte qui donne une réponse honnête à l'opération abstract [[HasProperty]]
. Au moment d'écrire ces lignes, les navigateurs font un très bon travail dans ce domaine, mais la spécification 5.1 permettait la possibilité qu'un objet fourni par l'hôte ne soit pas honnête. C'est dans §8.6.2 , plusieurs paragraphes en dessous de la grande table vers le début de cette section), où il est écrit:
Les objets hôtes peuvent implémenter ces méthodes internes de n'importe quelle manière, sauf indication contraire. Par exemple, une possibilité est que _
[[Get]]
_ et _[[Put]]
_ pour un objet hôte particulier récupère et stocke les valeurs de propriété, mais _[[HasProperty]]
_ génère toujoursfalse.
(Je ne pouvais pas trouver le verbiage équivalent dans la spécification ES2015, mais il est certain que ce sera toujours le cas.) Encore une fois, à la date de cette écriture, les objets communs de type tableau fournis par l'hôte dans les navigateurs modernes [NodeList
instances, par exemple]dohandle _[[HasProperty]]
_ correctement, mais il est important de tester.)
Edit: Cette réponse est désespérément obsolète. Pour une approche plus moderne, regardez les méthodes disponibles sur un tableau . Les méthodes d'intérêt pourraient être:
La méthode standard pour itérer un tableau dans JavaScript est une boucle Vanilla for
-:
var length = arr.length,
element = null;
for (var i = 0; i < length; i++) {
element = arr[i];
// Do something with element
}
Notez cependant que cette approche n’est utile que si vous avez un tableau dense et que chaque index est occupé par un élément. Si le tableau est clairsemé, vous pouvez rencontrer des problèmes de performances avec cette approche, car vous effectuerez une itération sur un grand nombre d'indices qui n'existent pas vraiment dans le tableau. Dans ce cas, une boucle for .. in
- pourrait être une meilleure idée. Cependant, vous devez utiliser les sauvegardes appropriées pour vous assurer que seules les propriétés souhaitées du tableau (c'est-à-dire les éléments du tableau) sont utilisées, car la boucle for..in
- sera également énumérée dans les anciens navigateurs, ou si le les propriétés supplémentaires sont définies en tant que enumerable
.
Dans ECMAScript 5 , il y aura une méthode forEach sur le prototype de tableau, mais elle n'est pas prise en charge par les navigateurs hérités. Donc, pour pouvoir l'utiliser de manière cohérente, vous devez disposer d'un environnement qui le prend en charge (par exemple, Node.js pour JavaScript côté serveur) ou utiliser un "Polyfill". Le Polyfill pour cette fonctionnalité est cependant trivial et, puisqu'il facilite la lecture du code, il est bon de l'inclure.
Si vous utilisez la bibliothèque jQuery , vous pouvez utiliser jQuery.each :
$.each(yourArray, function(index, value) {
// do your stuff here
});
MODIFIER :
Selon la question, l’utilisateur veut du code en javascript au lieu de jquery afin que la modification soit
var length = yourArray.length;
for (var i = 0; i < length; i++) {
// Do something with yourArray[i].
}
Certains langages de style C - utilisent foreach
pour parcourir les énumérations en boucle. En JavaScript, cela se fait avec la structure de boucle for..in
:
var index,
value;
for (index in obj) {
value = obj[index];
}
Il y a une prise. for..in
parcourt chacun des membres énumérables de l'objet et les membres de son prototype. Pour éviter de lire les valeurs héritées du prototype de l'objet, vérifiez simplement si la propriété appartient à l'objet:
for (i in obj) {
if (obj.hasOwnProperty(i)) {
//do stuff
}
}
De plus, ECMAScript 5 a ajouté une méthode forEach
à Array.prototype
qui peut être utilisée pour énumérer un tableau à l'aide d'un calback (le polyfill se trouve dans la documentation afin que vous puissiez toujours l'utiliser pour les navigateurs plus anciens):
arr.forEach(function (val, index, theArray) {
//do stuff
});
Il est important de noter que Array.prototype.forEach
ne s'interrompt pas lorsque le rappel retourne false
. jQuery et Underscore.js fournissent leurs propres variations sur each
afin de fournir des boucles pouvant être court-circuitées.
Si vous souhaitez effectuer une boucle sur un tableau, utilisez la boucle for
standard en trois parties.
for (var i = 0; i < myArray.length; i++) {
var arrayItem = myArray[i];
}
Vous pouvez obtenir certaines optimisations de performances en mettant en cache myArray.length
ou en effectuant une itération inverse.
Si cela ne vous dérange pas de vider le tableau:
var x;
while(x = y.pop()){
alert(x); //do something
}
x
contiendra la dernière valeur de y
et elle sera supprimée du tableau. Vous pouvez également utiliser shift()
qui donnera et supprimera le premier élément de y
.
Une implémentation de forEach ( voir dans jsFiddle ):
function forEach(list,callback) {
var length = list.length;
for (var n = 0; n < length; n++) {
callback.call(list[n]);
}
}
var myArray = ['hello','world'];
forEach(
myArray,
function(){
alert(this); // do something
}
);
Une solution simple consisterait maintenant à utiliser la bibliothèque underscore.js . Il fournit de nombreux outils utiles, tels que each
, et déléguera automatiquement le travail à la variable forEach
si disponible.
Un exemple de CodePen de comment cela fonctionne est:
var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});
Array.prototype.forEach()
natif .for each (variable in object)
est déconseillé dans la norme ECMA-357 ( EAX ).for (variable of object)
dans le cadre de la proposition Harmony (ECMAScript 6).Il existe trois implémentations de foreach
dans jQuery comme suit.
var a = [3,2];
$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3
La boucle for(i = 0; i < array.length; i++)
n'est probablement pas le meilleur choix. Pourquoi? Si vous avez ceci:
var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";
La méthode appellera de array[0]
à array[2]
. Premièrement, ceci va tout d'abord référencer les variables que vous n'avez même pas, ensuite vous n'auriez pas les variables dans le tableau, et troisièmement, cela rendra le code plus gras. Regardez ici, c'est ce que j'utilise:
for(var i in array){
var el = array[i];
//If you want 'i' to be INT just put parseInt(i)
//Do something with el
}
Et si vous voulez que ce soit une fonction, vous pouvez faire ceci:
function foreach(array, call){
for(var i in array){
call(array[i]);
}
}
Si vous voulez rompre, un peu plus de logique:
function foreach(array, call){
for(var i in array){
if(call(array[i]) == false){
break;
}
}
}
Exemple:
foreach(array, function(el){
if(el != "!"){
console.log(el);
} else {
console.log(el+"!!");
}
});
Il retourne:
//Hello
//World
//!!!
À partir de ES6:
list = [0, 1, 2, 3]
for (let obj of list) {
console.log(obj)
}
Où of
évite les bizarreries associées à in
et la fait fonctionner comme la boucle for
de toute autre langue, et let
lie i
dans la boucle et non dans la fonction.
Les accolades ({}
) peuvent être omises lorsqu'il n'y a qu'une seule commande (par exemple, dans l'exemple ci-dessus).
Il s’agit d’un itérateur pour une liste non fragmentée dont l’index commence à 0, ce qui est le scénario typique lorsqu’il s’agit de document.getElementsByTagName ou document.querySelectorAll)
function each( fn, data ) {
if(typeof fn == 'string')
eval('fn = function(data, i){' + fn + '}');
for(var i=0, L=this.length; i < L; i++)
fn.call( this[i], data, i );
return this;
}
Array.prototype.each = each;
Exemples d'utilisation:
Exemple 1
var arr = [];
[1, 2, 3].each( function(a){ a.Push( this * this}, arr);
arr = [1, 4, 9]
Exemple # 2
each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');
Chaque balise p reçoit class="blue"
Exemple # 3
each.call(document.getElementsByTagName('p'),
"if( i % 2 == 0) this.className = data;",
'red'
);
Chaque autre balise p reçoit class="red"
>
Exemple # 4
each.call(document.querySelectorAll('p.blue'),
function(newClass, i) {
if( i < 20 )
this.className = newClass;
}, 'green'
);
Et enfin, les 20 premiers tags p bleus sont changés en vert
Attention lors de l'utilisation de chaîne comme fonction: la fonction est créée hors contexte et ne doit être utilisée que si vous êtes certain de la portée des variables. Sinon, il vaut mieux passer les fonctions où la portée est plus intuitive.
Il n'y a pas de boucle for each
en natif JavaScript . Vous pouvez utiliser les bibliothèques pour obtenir cette fonctionnalité (je recommande Underscore.js ), utilisez une simple boucle for
in.
for (var instance in objects) {
...
}
Cependant, notez qu'il peut y avoir des raisons d'utiliser une boucle for
encore plus simple (voir la question Débordement de pile Pourquoi l'utilisation de “for… in” avec une itération de tableau est-elle une si mauvaise idée?)
var instance;
for (var i=0; i < objects.length; i++) {
var instance = objects[i];
...
}
Il y a quelques façons de parcourir un tableau en JavaScript, comme ci-dessous:
pour - c'est le plus commun. Bloc complet de code pour la mise en boucle
var languages = ["Java", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>
while - boucle lorsqu'une condition est remplie. Cela semble être la boucle la plus rapide
var text = "";
var i = 0;
while (i < 10) {
text += i + ") something<br>";
i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>
do/while - Parcourt également un bloc de code lorsque la condition est vraie et s'exécutera au moins une fois.
var text = ""
var i = 0;
do {
text += i + ") something <br>";
i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>
Boucles fonctionnelles - forEach
, map
, filter
, aussi reduce
(ils parcourent la fonction en boucle, mais sont utilisés si vous avez besoin de modifier votre tableau, etc.
// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>
Pour plus d'informations et d'exemples sur la programmation fonctionnelle de tableaux, consultez l'article de blog Programmation fonctionnelle en JavaScript: mapper, filtrer et réduire.
ECMAScript5 (la version sur Javascript) pour travailler avec des tableaux.
forEach - Itère à travers tous les éléments du tableau et fait tout ce dont vous avez besoin avec chaque élément.
['C', 'D', 'E'].forEach(function(element, index) {
console.log(element + " is the #" + (index+1) + " in musical scale");
});
// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale
Au cas où, plus intéressé par le fonctionnement sur tableau en utilisant une fonctionnalité intégrée.
map - Il crée un nouveau tableau avec le résultat de la fonction de rappel. Cette méthode est utile si vous avez besoin de formater les éléments de votre tableau.
// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
return elem.toUpperCase();
});
// Output: ['BOB', 'JOE', 'JEN']
reduction - Comme son nom l'indique, il réduit le tableau à une valeur unique en appelant la fonction donnée transmettant l'élément currenct et le résultat de l'exécution précédente.
[1,2,3,4].reduce(function(previous, current) {
return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10
every - Renvoie true ou false si tous les éléments du tableau réussissent le test de la fonction de rappel.
// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];
ages.every(function(elem) {
return elem >= 18;
});
// Output: false
filter - Très similaire à tous sauf que filter retourne un tableau avec les éléments qui retournent true à la fonction donnée.
// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
return (elem % 2 == 0)
});
// Output: [2,4,6]
J'espère que cela vous sera utile.
Il n'y a pas de capacité incorporée à roder forEach
. Pour interrompre l'exécution, utilisez le Array#some
comme ci-dessous:
[1,2,3].some(function(number) {
return number === 1;
});
Cela fonctionne car some
renvoie true dès que l'un des rappels, exécuté dans l'ordre du tableau, renvoie true, court-circuitant l'exécution du reste. Réponse originale Voir le prototype de tableau pour some
J'aimerais également ajouter ceci en tant que composition d'une boucle inversée et réponse ci-dessus à quelqu'un qui aimerait aussi cette syntaxe.
var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
console.log(item);
}
Avantages:
L'avantage pour cela: vous avez déjà la référence dans la première, car il ne sera pas nécessaire de la déclarer ultérieurement avec une autre ligne. C'est pratique lorsque vous passez en boucle dans le tableau d'objets.
Les inconvénients:
Cela cassera chaque fois que la référence est fausse - falsey (indéfini, etc.). Il peut être utilisé comme avantage cependant. Cependant, cela rendrait la lecture un peu plus difficile. Et également en fonction du navigateur, il peut être "non" optimisé pour fonctionner plus rapidement que celui d'origine.
manière jQuery utilisant $.map
:
var data = [1, 2, 3, 4, 5, 6, 7];
var newData = $.map(data, function(element) {
if (element % 2 == 0) {
return element;
}
});
// newData = [2, 4, 6];
Une méthode plus proche de votre idée serait d’utiliser Array.forEach()
qui accepte une fonction de verrouillage qui sera exécutée pour chaque élément du tableau.
myArray.forEach(
(item) => {
// do something
console.log(item);
}
);
Une autre solution viable consisterait à utiliser Array.map()
qui fonctionne de la même manière, mais aussi à mutates
chaque élément et le renvoie comme suit:
var myArray = [1, 2, 3];
myArray = myArray.map(
(item) => {
return item + 1;
}
);
console.log(myArray); // [2, 3, 4]
Utilisation des boucles avec ES6 déstructuration et opérateur d'étalement
La destruction et l'utilisation de l'opérateur de propagation se sont révélées très utiles pour les nouveaux arrivants à ES6, car ils sont plus lisibles/esthétiques, bien que certains anciens combattants du javascript puissent le considérer comme désordonné, que des juniors ou d'autres personnes puissent le trouver utile.
Les exemples suivants utiliseront l'instruction
for...of
et la méthode.forEach
.Les exemples 6, 7 et 8 peuvent être utilisés avec toutes les boucles fonctionnelles telles que
.map
,.filter
,.reduce
,.sort
,.every
,.some
, pour plus d'informations sur ces méthodes, consultez le Array Object .
Exemple 1: Normal for...of
loop - pas d'astuce ici.
let arrSimple = ['a', 'b', 'c'];
for (let letter of arrSimple) {
console.log(letter);
}
Exemple 2: Fractionner des mots en caractères
let arrFruits = ['Apple', 'orange', 'banana'];
for (let [firstLetter, ...restOfTheWord] of arrFruits) {
// Create a shallow copy using the spread operator
let [lastLetter] = [...restOfTheWord].reverse();
console.log(firstLetter, lastLetter, restOfTheWord);
}
Exemple 3: Boucle avec une key
et value
// let arrSimple = ['a', 'b', 'c'];
// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type:
// `arrWithIndex: [number, string][]`
let arrWithIndex = [
[0, 'a'],
[1, 'b'],
[2, 'c'],
];
// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);
// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on internet Explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);
for (let [key, value] of arrWithIndex) {
console.log(key, value);
}
Exemple 4: Obtenir les propriétés de l'objet en ligne
let arrWithObjects = [{
name: 'Jon',
age: 32
},
{
name: 'Elise',
age: 33
}
];
for (let { name, age: aliasForAge } of arrWithObjects) {
console.log(name, aliasForAge);
}
Exemple 5: Obtenir les propriétés de l'objet dont vous avez besoin
let arrWithObjectsWithArr = [{
name: 'Jon',
age: 32,
tags: ['driver', 'chef', 'jogger']
},
{
name: 'Elise',
age: 33,
tags: ['best chef', 'singer', 'dancer']
}
];
for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
console.log(name, firstItemFromTags, restOfTags);
}
Exemple 6: Est Exemple 3 utilisé avec .forEach
let arrWithIndex = [
[0, 'a'],
[1, 'b'],
[2, 'c'],
];
// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it
arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
console.log(forEachIndex, mappedIndex, item);
});
Exemple 7: Est Exemple 4 utilisé avec .forEach
let arrWithObjects = [{
name: 'Jon',
age: 32
},
{
name: 'Elise',
age: 33
}
];
// NOTE: Destructuring objects while using shorthand functions
// are required to be surrounded by parenthesis
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
console.log(name, aliasForAge)
});
Exemple 8: Est Exemple 5 utilisé avec .forEach
let arrWithObjectsWithArr = [{
name: 'Jon',
age: 32,
tags: ['driver', 'chef', 'jogger']
},
{
name: 'Elise',
age: 33,
tags: ['best chef', 'singer', 'dancer']
}
];
arrWithObjectsWithArr.forEach(({
name,
tags: [firstItemFromTags, ...restOfTags]
}) => {
console.log(name, firstItemFromTags, restOfTags);
});
La syntaxe lambda ne fonctionne généralement pas dans IE 10 ou moins.
J'utilise habituellement le
[].forEach.call(arrayName,function(value,index){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters
$("#ul>li").each(function(**index,value**){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
Vous pouvez appeler pour chaque chose comme ceci:
let Array = [1,3,2];
theArray.forEach((element)=>{
// use the element of the array
console.log(element)
}
element aura la valeur de chaque index de 0 a la longueur du tableau.
Sortie:
1
3
2
Explication
forEach est dans la classe prototype. vous pouvez aussi appeler cela comme theArray.prototype.forEach (...);
prototype: https://hackernoon.com/prototypes-in-javascript-5bba2990e04b
Vous pouvez également modifier un tableau comme ceci:
for(let i=0;i<theArray.length;i++){
console.log(i); //i will have the value of each index
}
si vous voulez parcourir un tableau d'objets avec une fonction de flèche:
let arr=[{name:'john',age:50},{name:'clark',age:19},{name:'mohan',age:26}];
arr.forEach((person)=>{
console.log('i am '+person.name+' and i am '+person.age+ ' old');
})
Lors d'une itération sur un tableau, nous pouvons souvent vouloir atteindre l'un des objectifs suivants:
Nous voulons parcourir le tableau et créer un nouveau tableau:
Array.prototype.map
Nous voulons parcourir le tableau sans créer de nouveau tableau:
Array.prototype.forEach
for..of
boucle
Dans JS, il existe de nombreuses façons d’atteindre ces deux objectifs. Cependant, certains sont plus conventionnels que d'autres. Ci-dessous, vous trouverez quelques méthodes couramment utilisées (la plus conventionnelle) pour effectuer une itération de tableau en javascript.
Map
map()
est une fonction située sur Array.prototype
qui peut transformer chaque élément d'un tableau puis retourne un new array. map()
prend en argument une fonction de rappel et fonctionne de la manière suivante:
let arr = [1, 2, 3, 4, 5];
let newArr = arr.map((element, index, array) => {
return element * 2;
})
console.log(arr);
console.log(newArr);
Le rappel que nous avons transmis à map()
en tant qu'argument est exécuté pour chaque élément. Ensuite, un tableau est renvoyé qui a la même longueur que le tableau d'origine. Dans ce nouvel élément de tableau, la fonction de rappel transmise sous forme d'argument à map()
est transformée.
La différence distincte entre map
et un autre mécanisme de boucle tel que forEach
et une boucle for..of
réside dans le fait quemap
est renvoyé sous la forme d'un nouveau tableau et laisse le tableau ancien intact (sauf si vous le manipulez explicitement avec la méthode splice
.
Notez également que le rappel de la fonction map
fournit comme deuxième argument le numéro d'index de l'itération en cours. De plus, le troisième argument fournit le tableau sur lequel map
a été appelé. Parfois, ces propriétés peuvent être très utiles.
forEach
forEach
est une fonction située sur Array.prototype
qui prend une fonction de rappel en tant qu'argument. Il exécute ensuite cette fonction de rappel pour chaque élément du tableau. Contrairement à la fonction map()
, la fonction forEach ne renvoie rien (undefined
). Par exemple:
let arr = [1, 2, 3, 4, 5];
arr.forEach((element, index, array) => {
console.log(element * 2);
if (index === 4) {
console.log(array)
}
// index, and oldArray are provided as 2nd and 3th argument by the callback
})
console.log(arr);
Tout comme la fonction map
, le rappel forEach
fournit comme deuxième argument le numéro d'index de l'itération en cours. Le troisième argument fournit également le tableau sur lequel forEach
a été appelé.
for..of
La boucle for..of
parcourt tous les éléments d'un tableau (ou tout autre objet itérable). Cela fonctionne de la manière suivante:
let arr = [1, 2, 3, 4, 5];
for(let element of arr) {
console.log(element * 2);
}
Dans l'exemple ci-dessus, element
représente un élément de tableau et arr
est le tableau que nous voulons boucler. Non pas que le nom element
soit arbitraire et nous aurions pu choisir un autre nom comme 'el' ou quelque chose de plus déclaratif lorsque cela est applicable.
Ne confondez pas la boucle for..in
avec la boucle for..of
. for..in
parcourt toutes les propriétés énumérables du tableau alors que la boucle for..of
parcourt uniquement les éléments du tableau. Par exemple:
let arr = [1, 2, 3, 4, 5];
arr.foo = 'foo';
for(let element of arr) {
console.log(element);
}
for(let element in arr) {
console.log(element);
}
Si vous avez un tableau énorme, utilisez iterators
pour gagner en efficacité. Les itérateurs sont une propriété de certaines collections JavaScript (comme Map
, Set
, String
, Array
). Même, for..of
utilise iterator
sous le capot.
Les itérateurs améliorent l'efficacité en vous permettant de consommer les éléments d'une liste, l'un après l'autre, comme s'il s'agissait d'un flux. Ce qui rend un itérateur spécial, c'est la façon dont il parcourt une collection. Les autres boucles doivent charger toute la collection à l’avance pour pouvoir être parcourues, alors qu’un itérateur n’a besoin que de connaître la position actuelle dans la collection.
Vous accédez à l’élément en cours en appelant la méthode next
de l’itérateur. La méthode suivante renverra la value
de l'élément actuel et une boolean
pour indiquer le moment où vous avez atteint la fin de la collection. Voici un exemple de création d'un itérateur à partir d'un tableau.
Transformez votre tableau régulier en itérateur à l’aide de values()
comme ceci:
const myArr = [2,3,4]
let it = myArr.values();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
Vous pouvez également transformer votre tableau régulier en itérateur à l’aide de Symbol.iterator
comme ceci:
const myArr = [2,3,4]
let it = myArr[Symbol.iterator]();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
Vous pouvez également transformer votre array
régulière en un iterator
comme ceci:
let myArr = [8, 10, 12];
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
};
};
var it = makeIterator(myArr);
console.log(it.next().value); // {value: 8, done: false}
console.log(it.next().value); // {value: 10, done: false}
console.log(it.next().value); // {value: 12, done: false}
console.log(it.next().value); // {value: undefined, done: true}
REMARQUE:
iterable
par défaut. Utilisez for..in
dans ce cas car au lieu de valeurs, cela fonctionne avec des clés.Vous pouvez en savoir plus sur iteration protocol
ici .
var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
console.log("Index" + index);
console.log("Element" + item);
})
// Looping through arrays using foreach ES6 way
var data = new Array(1,2,3,4,5);
data.forEach((val,index) => {
console.log("index :",index); // index
console.log("value :", val); // value
});
Vous pouvez utiliser forEach () API (fournie par Javascript) qui accepte une fonction en tant que rappel et s'exécute une fois pour chaque élément présent dans le tableau.
https://fullstackgeek.blogspot.com/2019/01/arrays-in-javascript-part-2.html
Je viens de python et j'ai trouvé cela beaucoup plus clair.
theArray étant le tableau, instance étant l'élément du tableau
for(let instance of theArray)
{
console.log("The instance",instance);
}
ou
for( instance in theArray)
{
console.log("The instance",instance);
}
comparer aux:
theArray.forEach(function(instance) {
console.log(instance);
});
mais à la fin de la journée, les deux font la même chose
Si vous voulez conserver votre code de manière fonctionnelle, utilisez map:
theArray.map(instance => do_something);
De cette façon, vous générerez un nouveau tableau pour les opérations futures et vous éviterez tout effet secondaire indésirable.
Si vous voulez utiliser forEach()
, cela ressemblera à -
theArray.forEach ( element => {
console.log(element);
});
Si vous voulez utiliser for()
, cela ressemblera à -
for(let idx = 0; idx < theArray.length; idx++){
let element = theArray[idx];
console.log(element);
}