Javascript foreach loop sull'oggetto array associativo


182

Perché il mio ciclo for-each non sta ripetendo il mio oggetto array associativo 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()potrebbe essere utile: https://api.jquery.com/jQuery.each/


1
Si crea un array ma lo si utilizza come una mappa. Sembra invece che tu voglia un oggetto semplice.
Jon,

4
Non ci sono cose come associative arraysin JS: è una semplice matrice o un oggetto. Nulla impedisce di aggiungere proprietà non numeriche Array, ma ciò non lo rende associative- in particolare, la lengthproprietà non conteggerà automaticamente queste proprietà.
raina77ow,

3
ri: Non ci sono cose come array associativi in ​​JS. - formulato in altro modo: JavaScript utilizza il nome "Oggetto" anziché il nome "matrice associativa". Ma non ha una proprietà ".length".
Jesse Chisholm,

Risposte:


315

La .lengthproprietà tiene traccia solo delle proprietà con indici numerici (chiavi). Stai usando le stringhe per i tasti.

Puoi farlo:

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

Per sicurezza, è una buona idea in cicli del genere per assicurarsi che nessuna delle proprietà sia un risultato inaspettato dell'ereditarietà:

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

modifica - è probabilmente una buona idea ora notare che la Object.keys()funzione è disponibile sui browser moderni e in Nodo ecc. Quella funzione restituisce le chiavi "proprie" di un oggetto, come un array:

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

La funzione di callback passata .forEach()viene chiamata con ogni chiave e l'indice della chiave nell'array restituito da Object.keys(). Ha anche passato l'array attraverso il quale la funzione sta ripetendo, ma quell'array non ci è veramente utile; abbiamo bisogno dell'oggetto originale . È possibile accedervi direttamente per nome, ma (secondo me) è un po 'più bello passarlo esplicitamente, cosa che viene fatta passando un secondo argomento a .forEach()- l'oggetto originale - che verrà associato come thisall'interno del callback. (Ho appena visto che questo è stato notato in un commento qui sotto.)


Che var arr_jq_TabContents = {};cos'è questo ? Voglio dire {}
Szymon Toda,

1
@Ultra è un oggetto vuoto letterale. Significa solo che la variabile è inizializzata con un riferimento a un nuovo oggetto vuoto.
Pointy,

@Ultra non hai bisogno di un'istanza di array perché in quel codice non lo stai usando come un array JavaScript. JavaScript non ha "array associativi" come alcune altre lingue.
Pointy,

1
Qual è la differenza tra assegnare []e {}? Solo i diversi prototipi?
Presto,

8
Invece di usare hasOwnProperty dovrebbe essere possibile in tutti i moderni browser Web scorrere le chiavi di un oggetto usando: Object.keys(arr_jq_TabContents).forEach( function(key) { ... } );
Gregory Bell

80

Questo è un approccio molto semplice. Il vantaggio è che puoi ottenere anche le chiavi:

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

Per ES6:

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

Per ES6: (se si desidera il valore, l'indice e l'array stesso)

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

12
Non usare varin loop che suggeriscono scoping che non esiste. Utilizzare vardavanti al loop o letnel loop.
ceving

2
@ceving, puoi spiegare di più sul perché non usare var nei loop? Vengo dallo sfondo C ++ / PHP e non lo capisco. l'ambito esiste nel ciclo, ma è temporaneo, quindi non sono sicuro di cosa tu voglia dire.
Dennis,

6
@Dennis Nella maggior parte delle lingue una dichiarazione variabile in un forciclo genera un ambito limitato al corpo del forciclo. Ma in JavaScript una variabile dichiarata da varè sempre funzione globale anche se la scrivi in ​​un forciclo. Vedere qui: davidwalsh.name/for-and-against-let
ceving

1
non perdite di memoria in sé, ma sicuramente "sversamenti di memoria". varin Javascript crea variabili in memoria anche al termine del ciclo.
ahnbizcad

Penso che il punto di questi commenti sull'uso di "var" sia ora usare "let" in generale, ma specificamente in un ciclo. I motivi sono spiegati sopra ma in sintesi è dovuto all'ambito, "var" crea un ambito globale.
DeeZone,

6

Ci sono già alcuni esempi chiari, ma noto da come hai formulato la tua domanda che probabilmente provieni da uno sfondo di PHP e ti aspetti che JavaScript funzioni allo stesso modo - non funziona. Un PHP arrayè molto diverso da un JavaScriptArray .

In PHP, un array associativo può fare la maggior parte di ciò che un array indicizzato numericamente (le array_*funzioni funzionano, puoicount() , ecc.) È sufficiente creare un array e iniziare ad assegnare agli indici di stringa invece che numerici.

In JavaScript, tutto è un oggetto (ad eccezione delle primitive: stringa, numerico, booleano) e le matrici sono una certa implementazione che ti consente di avere indici numerici. Qualsiasi cosa spinta a un array avrà effettolength , e può essere iterata con metodi Array ( map, forEach, reduce, filter, find, ecc) Tuttavia, perché tutto è un oggetto, sei sempre libero di semplici proprietà assegnare, perché è qualcosa che si fa per qualsiasi oggetto. La notazione a parentesi quadre è semplicemente un altro modo per accedere a una proprietà, quindi nel tuo caso:

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

è effettivamente equivalente a:

array.Main = 'Main Page';

Dalla tua descrizione, suppongo che tu voglia un "array associativo", ma per JavaScript, questo è un semplice caso di utilizzo di un oggetto come hashmap. Inoltre, so che è un esempio, ma evita i nomi non significativi che descrivono solo il tipo di variabile (ad esempio array) e il nome in base a ciò che dovrebbe contenere (ad esempio pages). Gli oggetti semplici non hanno molti buoni modi diretti per iterare, quindi spesso trasformeremo poi in array prima usando i Objectmetodi ( Object.keysin questo caso - c'è anche entriese valuesvenendo aggiunti ad alcuni browser proprio ora) che possiamo eseguire in loop.

// 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] vede l'array come un modulo 0-index.


4

Ecco un modo semplice per usare un array associativo come un tipo di oggetto generico:

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

Questo è (essenzialmente) errato nella maggior parte dei casi:

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

Ciò crea una proprietà non element sull'array con il nome Main. Sebbene le matrici siano oggetti, normalmente non si desidera creare su di essi proprietà non elementali.

Se si desidera indicizzare in arraybase a tali nomi, in genere si utilizza uno Mapo un oggetto semplice, non un array.

Con un Map(ES2015 +), che chiamerò mapperché sono creativo:

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

poi iterare utilizzando gli iteratori dai suoi values, keys, o entriesmetodi, per esempio:

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

Usando un oggetto semplice, che chiamerò in modo creativo obj:

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

si sarebbe poi iterare il suo contenuto utilizzando Object.keys, Object.valueso Object.entries, per esempio:

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

in questo codice ho usato il metodo parentesi per i valori di chiamata in array perché conteneva array, tuttavia brevemente l'idea che una variabile i abbia una chiave di proprietà e con un ciclo chiamato entrambi i valori dell'array associato

Metodo perfetto, se ti interessa, premi mi piace


Non si esegue il looping attraverso un array, si esegue il looping di un oggetto che presenta array nelle relative chiavi. Leggere la domanda e guardare l'esempio.
Pedro Joaquín,

0

Puoi farlo

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)
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.