Boucle foreach Javascript sur un objet tableau associatif


182

Pourquoi ma boucle for for-each n'itère pas sur mon objet tableau associatif JavaScript?

// defining an array
var array = [];

// assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

EDIT: jQuery each()pourrait être utile: https://api.jquery.com/jQuery.each/


1
Vous créez un tableau, mais vous l'utilisez ensuite comme carte. Il semble que vous vouliez plutôt un objet simple.
Jon le

4
Il n'y a pas de choses comme associative arraysdans JS: c'est soit un tableau simple, soit un objet. Rien n'empêche d'ajouter des propriétés non numériques à Array, mais cela ne le fait pas associative- en particulier, la lengthpropriété ne compte pas automatiquement ces propriétés.
raina77ow

3
re: Il n'existe pas de tableaux associatifs dans JS. - libellé autrement: JavaScript utilise le nom "Objet" au lieu du nom "tableau associatif". Mais il n'a pas de propriété ".length".
Jesse Chisholm

Réponses:


315

La .lengthpropriété ne suit que les propriétés avec des index numériques (clés). Vous utilisez des chaînes pour les clés.

Tu peux le faire:

var arr_jq_TabContents = {}; // no need for an array

arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;

for (var key in arr_jq_TabContents) {
    console.log(arr_jq_TabContents[key]);
}

Pour être sûr, c'est une bonne idée dans des boucles comme celle-ci pour s'assurer qu'aucune des propriétés n'est un résultat inattendu d'héritage:

for (var key in arr_jq_TabContents) {
  if (arr_jq_TabContents.hasOwnProperty(key))
    console.log(arr_jq_TabContents[key]);
}

edit - c'est probablement une bonne idée maintenant de noter que la Object.keys()fonction est disponible sur les navigateurs modernes et dans Node etc. Cette fonction renvoie les "propres" clés d'un objet, sous forme de tableau:

Object.keys(arr_jq_TabContents).forEach(function(key, index) {
  console.log(this[key]);
}, arr_jq_TabContents);

La fonction de rappel passée à .forEach()est appelée avec chaque clé et l'index de la clé dans le tableau renvoyé par Object.keys(). Il est également passé le tableau à travers lequel la fonction itère, mais ce tableau ne nous est pas vraiment utile; nous avons besoin de l' objet original . On peut y accéder directement par nom, mais (à mon avis) c'est un peu plus agréable de le passer explicitement, ce qui se fait en passant un deuxième argument à .forEach()- l'objet d'origine - qui sera lié comme thisdans le rappel. (Je viens de voir que cela a été noté dans un commentaire ci-dessous.)


Qu'est-ce que c'est var arr_jq_TabContents = {};? Je veux dire {}
Szymon Toda

1
@Ultra c'est un objet littéral vide. Cela signifie simplement que la variable est initialisée avec une référence à un nouvel objet vide.
Pointy le

@Ultra vous n'avez pas besoin d'une instance Array car dans ce code, vous ne l'utilisez pas comme un tableau JavaScript. JavaScript n'a pas de "tableaux associatifs" comme certains autres langages.
Pointy le

1
Quelle est la différence entre attribuer []et {}? Seuls les différents prototypes?
SoonDead

8
Au lieu d'utiliser hasOwnProperty, il devrait être possible dans tous les navigateurs Web modernes d'itérer sur les clés d'un objet en utilisant: Object.keys(arr_jq_TabContents).forEach( function(key) { ... } );
Gregory Bell

80

C'est une approche très simple. L'avantage est que vous pouvez également obtenir des clés:

for (var key in array) {
    var value = array[key];
    console.log(key, value);
}

Pour ES6:

array.forEach(value => {
  console.log(value)
})  

Pour ES6: (Si vous voulez une valeur, un index et le tableau lui-même)

array.forEach((value, index, self) => {
  console.log(value, index, self)
})  

12
Ne pas utiliser vardans des boucles suggérant une portée qui n'existe pas. À utiliser vardevant la boucle ou letdans la boucle.
ceving

2
@ceving, pouvez-vous expliquer pourquoi ne pas utiliser var dans les boucles? Je viens de fond C ++ / PHP et je ne comprends pas cela. la portée existe dans la boucle, mais temporaire, donc je ne suis pas sûr de ce que vous voulez dire.
Dennis

6
@Dennis Dans la plupart des langages, une déclaration de variable dans une forboucle génère une portée limitée au corps de la forboucle. Mais en JavaScript, une variable déclarée par varest toujours une fonction globale même si vous l'écrivez dans une forboucle. Voir ici: davidwalsh.name/for-and-against-let
ceving

1
pas de fuites de mémoire en soi, mais certainement des "débordements de mémoire". varen Javascript crée des variables en mémoire même après la boucle.
ahnbizcad

Je pense que le but de ces commentaires concernant l'utilisation de "var" est maintenant d'utiliser "let" en général mais spécifiquement dans une boucle. Les raisons sont expliquées ci-dessus mais en résumé, c'est dû à la portée, "var" crée une portée globale.
DeeZone

6

Il existe déjà des exemples simples, mais je remarque, d'après la formulation de votre question, que vous venez probablement d'un arrière-plan PHP, et vous vous attendez à ce que JavaScript fonctionne de la même manière - ce n'est pas le cas. Un PHP arrayest très différent d'un JavaScript Array.

En PHP, un tableau associatif peut faire la plupart de ce qu'un tableau indexé numériquement peut (les array_*fonctions fonctionnent, vous pouvez le count()faire, etc.) Vous créez simplement un tableau et commencez à attribuer des index de chaîne au lieu de numériques.

En JavaScript, tout est un objet (à l'exception des primitives: chaîne, numérique, booléen), et les tableaux sont une certaine implémentation qui vous permet d'avoir des index numériques. Tout ce qui pousse à un tableau effectuera son length, et peut être itéré en utilisant des méthodes Array ( map, forEach, reduce, filter, find, etc.) Cependant, parce que tout est un objet, vous êtes toujours libre de simplement les propriétés Assigner, parce que quelque chose que vous faites pour n'importe quel objet. La notation entre crochets est simplement un autre moyen d'accéder à une propriété, donc dans votre cas:

array['Main'] = 'Main Page';

équivaut en fait à:

array.Main = 'Main Page';

D'après votre description, je suppose que vous voulez un «tableau associatif», mais pour JavaScript, il s'agit d'un cas simple d'utilisation d'un objet comme hashmap. Aussi, je sais que c'est un exemple, mais évitez les noms non significatifs qui décrivent uniquement le type de variable (par exemple array), et le nom en fonction de ce qu'il devrait contenir (par exemple pages). Les objets simples n'ont pas beaucoup de bons moyens directs d'itérer, donc souvent nous nous transformerons ensuite en tableaux en utilisant d'abord des Objectméthodes ( Object.keysdans ce cas - il y en a aussi entrieset en valuescours d'ajout à certains navigateurs en ce moment) que nous pouvons boucler.

// assigning values to corresponding keys
const pages = {
  Main: 'Main page',
  Guide: 'Guide page',
  Articles: 'Articles page',
  Forum: 'Forum board',
};

Object.keys(pages).forEach((page) => console.log(page));

4

arr_jq_TabContents[key] voit le tableau comme une forme d'index 0.


4

Voici un moyen simple d'utiliser un tableau associatif comme type d'objet générique:

Object.prototype.forEach = function(cb){
   if(this instanceof Array) return this.forEach(cb);
   let self = this;
   Object.getOwnPropertyNames(this).forEach(
      (k)=>{ cb.call(self, self[k], k); }
   );
};

Object({a:1,b:2,c:3}).forEach((value, key)=>{ 
    console.log(`key/value pair: ${key}/${value}`);
});



1

Ceci est (essentiellement) incorrect dans la plupart des cas:

var array = [];
array["Main"] = "Main page";

Cela crée une propriété non élémentaire sur le tableau avec le nom Main. Bien que les tableaux soient des objets, vous ne souhaitez normalement pas créer de propriétés non élémentaires sur eux.

Si vous souhaitez indexer arraypar ces noms, vous utiliserez généralement un Mapobjet ou un objet simple, pas un tableau.

Avec un Map(ES2015 +), que j'appellerai mapparce que je suis créatif:

let map = new Map();
map.set("Main", "Main page");

vous itérer ensuite à l'aide des itérateurs de ses values, keysou entriesméthodes, par exemple:

for (const value of map.values()) {
    // Here, `value` will be `"Main page"`, etc.
}

En utilisant un objet simple, que j'appellerai de manière créative obj:

let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`

vous auriez alors itérer son contenu en utilisant Object.keys, Object.valuesou Object.entries, par exemple:

for (const value of Object.values(proches_X)) {
    // Here, `value` will be `"Main page"`, etc.
}

0

var obj = {
  no: ["no", 32],
  nt: ["no", 32],
  nf: ["no", 32, 90]
};

count = -1; // which must be static value
for (i in obj) {
  count++;
  if (obj.hasOwnProperty(i)) {
    console.log(obj[i][count])
  };
};

dans ce code, j'ai utilisé la méthode des crochets pour les valeurs d'appel dans le tableau car il contenait un tableau, mais brièvement l'idée qu'une variable i a une clé de propriété et avec une boucle appelée les deux valeurs du tableau associé

Méthode parfaite, si vous êtes intéressé, appuyez sur comme


Vous n'êtes pas en train de faire une boucle avec un tableau, vous faites une boucle sur un objet qui a des tableaux dans ses clés. Veuillez lire la question et regarder l'exemple.
Pedro Joaquín le

0

Tu peux le faire

var array = [];

// assigning values to corresponding keys
array[0] = "Main page";
array[1] = "Guide page";
array[2] = "Articles page";
array[3] = "Forum board";


array.forEach(value => {
    console.log(value)
})
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.