Come posso scorrere o enumerare un oggetto JavaScript?


2881

Ho un oggetto JavaScript come il seguente:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Ora voglio scorrere tutti pgli elementi ( p1, p2, p3...) e ottenere il loro chiavi e valori. Come lo posso fare?

Posso modificare l'oggetto JavaScript se necessario. Il mio obiettivo finale è quello di scorrere alcune coppie di valori-chiave e, se possibile, voglio evitare di usarlo eval.


9
Ho modificato JSON in JavaScript (oggetto) per evitare confusione tra oggetti letterali e JSON.
Felix Kling

Risposte:


4369

Puoi usare il for-in loop come mostrato da altri. Tuttavia, devi anche assicurarti che la chiave che ottieni sia una proprietà reale di un oggetto e non provenga dal prototipo.

Ecco lo snippet:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

For-of con Object.keys () alternativa:

var p = {
    0: "value1",
    "b": "value2",
    key: "value3"
};

for (var key of Object.keys(p)) {
    console.log(key + " -> " + p[key])
}

Notare l'uso di for-ofinvece di for-in, se non usato, restituirà indefinito su proprietà denominate, eObject.keys() garantisce l'uso solo delle proprietà dell'oggetto senza le proprietà dell'intera catena prototipo

Utilizzando il nuovo Object.entries() metodo:

Nota: questo metodo non è supportato nativamente da Internet Explorer. Puoi prendere in considerazione l'utilizzo di un Polyfill per browser meno recenti.

const p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}

34
Proporrebbe di cambiare la linea di allerta solo per chiarezza inalert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley,

80
Puoi spiegare la necessità di hasOwnProperty? Cosa intendi per prototipo?
Kamaci,

331
In JavaScript, ogni oggetto ha un mucchio di coppie chiave-valore integrate che hanno meta-informazioni. Quando esegui il ciclo attraverso tutte le coppie chiave-valore per un oggetto, esegui il ciclo anche attraverso di esse. hasOwnPropery () li filtra.
danieltalsky,

57
In realtà, For ... in non è deprecato. Per ogni ... in è. Ma mi piace molto il termine archeologi ... Dovrò iniziare a usarlo.
Ben Y,

17
ogni oggetto in JavaScript (in realtà una coppia chiave-valore) ha una proprietà chiamata __proto__o prototype. Questa proprietà ha un riferimento al suo oggetto padre. Un oggetto eredita automaticamente la proprietà dal suo genitore. Questo è il motivo dell'uso hasOwnProperty, il che significa che siamo interessati alla proprietà degli oggetti e non a quella dei genitori.
Zubair Alam,

1104

Sotto ECMAScript 5, puoi combinare Object.keys()e Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

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

ECMAScript 6 aggiunge for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ECMAScript 8 aggiunge Object.entries()che evita di cercare ogni valore nell'oggetto originale:

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

È possibile combinare for...of, destrutturare e Object.entries:

for (const [key, value] of Object.entries(obj)) {
    console.log(key, value);
}

Entrambi Object.keys()e Object.entries()ripetono le proprietà nello stesso ordine di un for...inciclo ma ignorano la catena di prototipi . Vengono iterate solo le proprietà enumerabili dell'oggetto.


21
Perché lo standard non ha fornito Object.forEach(obj, function (value, key) {...})? :( Sicuramente obj.forEach(function...)sarebbe più breve e complementare Array.prototype.forEach, ma ciò rischierebbe che gli oggetti definiscano la propria forEachproprietà. Suppongo che le Object.keysprotezioni contro il callback modifichino le chiavi dell'oggetto.
David Harkness,

7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness,

7
@DavidHarkness Esistono Object.entries in ES2017. Lì puoi fare quanto segue: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([chiave, valore] è una matrice che distrugge, per accedere direttamente ad entrambi gli elementi. E devi avvolgere i parametri in parentesi aggiuntive.)
Andreas Linnert,

come ottengo indexla chiave in json? O se richiesto dovrei usare un contatore separato?
Saravanabalagi Ramachandran,

3
for...ofè standard ES6, non ES2016.
Rax Weber,

342

Devi usare il ciclo for-in

Ma fai molta attenzione quando usi questo tipo di loop, perché questo eseguirà il loop di tutte le proprietà lungo la catena del prototipo .

Pertanto, quando si utilizzano loop for-in, utilizzare sempre il hasOwnPropertymetodo per determinare se la proprietà corrente nell'iterazione è in realtà una proprietà dell'oggetto su cui si sta verificando:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}

31
Questo è meglio della soluzione di levik perché consente alla logica principale di essere solo un loop nidificato anziché due; rendendo più facile la lettura del codice. Anche se perderei le parentesi attorno al continuo; sono superflui.
SystemicPlural

52
Non rimuoverei { }personalmente perché un ifsenza di loro rende un po 'poco chiaro ciò che è parte del ife ciò che non lo è. Ma immagino che sia solo una questione di opinione :)
pimvdb

34
Sì, preferisco mantenere { }principalmente per evitare confusione se uno in seguito deve aggiungere qualcosa al ifcampo di applicazione.
Andreas Grech,

8
Leggendo il mio commento precedente, mi sono reso conto che non ho usato i termini corretti, perché ho detto "if scope"; ma tieni presente che JavaScript ha solo un ambito di funzione. Quindi quello che volevo dire era "if block".
Andreas Grech,

1
eomeroff, se sei davvero preoccupato per questo, potresti sempre fare qualcosa del genere: Object.prototype.hasOwnProperty.call(p, prop) Tuttavia, anche questo non può proteggere dalle manipolazioni di Object.prototype ...
jordancpaul,

252

La domanda non sarà completa se non menzioniamo metodi alternativi per il looping di oggetti.

Al giorno d'oggi molte librerie JavaScript ben note forniscono i propri metodi per iterare su raccolte, ovvero su array , oggetti e oggetti simili a array . Questi metodi sono comodi da usare e sono completamente compatibili con qualsiasi browser.

  1. Se lavori con jQuery , puoi usare il jQuery.each()metodo. Può essere utilizzato per scorrere senza soluzione di continuità sia su oggetti che su array:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. In Underscore.js puoi trovare il metodo _.each(), che scorre su un elenco di elementi, restituendo ciascuno a sua volta a una funzione fornita (presta attenzione all'ordine degli argomenti nella funzione iterata !):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash offre diversi metodi per scorrere le proprietà degli oggetti. Di base _.forEach()(o alias _.each()) è utile per eseguire il ciclo tra oggetti e matrici, tuttavia (!) Gli oggetti con lengthproprietà sono trattati come matrici e per evitare questo comportamento si consiglia di utilizzare _.forIn()e _.forOwn()metodi (questi hanno anche l' valueargomento che viene prima):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });

    _.forIn()esegue l'iterazione delle proprietà enumerabili proprie ed ereditate di un oggetto, mentre _.forOwn()esegue l'iterazione solo sulle proprie proprietà di un oggetto (fondamentalmente verificando la hasOwnPropertyfunzione). Per oggetti semplici e letterali di oggetti ciascuno di questi metodi funzionerà bene.

Generalmente tutti i metodi descritti hanno lo stesso comportamento con qualsiasi oggetto fornito. Oltre a utilizzare il for..inciclo nativo , di solito è più veloce di qualsiasi astrazione, ad esempio jQuery.each()questi metodi sono notevolmente più facili da usare, richiedono meno codifica e forniscono una migliore gestione degli errori.


4
Per arrivare al valore: $ .each (obj, function (key, value) {console.log (value.title);});
Ravi Ram,

2
Semplicemente divertente come il carattere di sottolineatura e jquery
abbiano

52

In ECMAScript 5 hai un nuovo approccio nei campi di iterazione letterale - Object.keys

Maggiori informazioni che puoi vedere su MDN

La mia scelta è di seguito una soluzione più veloce nelle versioni correnti dei browser (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Puoi confrontare le prestazioni di questo approccio con diverse implementazioni su jsperf.com :

Supporto per il browser che puoi vedere sulla tabella di compatibilità di Kangax

Per il vecchio browser hai polyfill semplice e completo

UPD:

confronto delle prestazioni per tutti i casi più popolari in questa domanda su perfjs.info:

iterazione letterale dell'oggetto


In effetti, volevo solo pubblicare questo metodo. Ma mi hai battuto :(
Jamie Hutber,

50

Prefazione:

  • Le proprietà dell'oggetto possono essere proprie (la proprietà si trova sull'oggetto stesso) o ereditate (non sull'oggetto stesso, su uno dei suoi prototipi).
  • Le proprietà dell'oggetto possono essere enumerabili o non enumerabili . Le proprietà non enumerabili vengono escluse da molte enumerazioni / matrici di proprietà.
  • I nomi delle proprietà possono essere stringhe o simboli. Le proprietà i cui nomi sono Simboli sono escluse da molte enumerazioni / matrici di proprietà.

Qui nel 2018, le opzioni per scorrere ciclicamente le proprietà di un oggetto sono (alcuni esempi seguono l'elenco):

  1. for-in[ MDN , spec ] - Una struttura ad anello che scorre attraverso i nomi delle proprietà enumerabili di un oggetto , inclusi quelli ereditati, i cui nomi sono stringhe
  2. Object.keys[ MDN , spec ] - Una funzione che fornisce una serie di nomi di di un oggetto proprie , enumerabili proprietà i cui nomi sono stringhe.
  3. Object.values[ MDN , spec ] - Una funzione che fornisce una matrice dei valori di di un oggetto proprie , enumerabili proprietà.
  4. Object.entries[ MDN , spec ] - Una funzione che fornisce un array di nomi e valori di un oggetto proprie , enumerabili proprietà (ogni voce nella matrice è una [name, value]matrice).
  5. Object.getOwnPropertyNames[ MDN , spec ] - Una funzione che fornisce una serie di nomi di di un oggetto proprie proprietà (anche quelli non enumerabili) i cui nomi sono stringhe.
  6. Object.getOwnPropertySymbols[ MDN , spec ] - Una funzione che fornisce un allineamento dei nomi di un oggetto di proprie strutture (anche quelli non enumerabili) cui nomi sono simboli.
  7. Reflect.ownKeys[ MDN , spec ] - Una funzione che fornisce un allineamento dei nomi di un oggetto di proprie strutture (anche quelli non enumerabili), se tali nomi sono stringhe o simboli.
  8. Se si desidera che tutti di proprietà di un oggetto, inclusi quelli ereditati non enumerabili, è necessario utilizzare un ciclo e Object.getPrototypeOf[ MDN , spec ] e l'uso Object.getOwnPropertyNames, Object.getOwnPropertySymbolso Reflect.ownKeyssu ogni oggetto nella catena di prototipi (ad esempio in fondo a questa risposta).

Con tutti loro, tranne for-in, utilizza una sorta di loop costrutto sulla matrice ( for, for-of, forEach, etc.).

Esempi:

for-in:

Object.keys (con un for-ofciclo, ma puoi usare qualsiasi costrutto di ciclo) :

Object.values:

Object.entries:

Object.getOwnPropertyNames:

Object.getOwnPropertySymbols:

Reflect.ownKeys:

Tutte le proprietà , comprese quelle non enumerabili ereditate:


Bella aggiunta di proprietà oggetto enumerabili / non enumerabili.
serraosays,

49

Puoi solo iterare su di esso come:

for (var key in p) {
  alert(p[key]);
}

Nota che keynon assumerà il valore della proprietà, è solo un valore di indice.


13
Questo è ripetuto e nemmeno del tutto corretto. Devi avere un controllo di hasOwnProperty per farlo funzionare correttamente
Vatsal

4
Inizialmente ho effettuato il downgrade di questo in base al commento sopra finché non mi sono reso conto che questa risposta è arrivata prima, quindi non viene "ripetuta". È forse incompleto ma funziona bene per molti casi.
Billynoah,

27

Poiché es2015 sta diventando sempre più popolare, sto inviando questa risposta che include l'uso di generatore e iteratore per scorrere senza problemi le [key, value]coppie. Come è possibile in altre lingue, ad esempio Ruby.

Ok ecco un codice:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Tutte le informazioni su come eseguire un iteratore e un generatore sono disponibili sulla pagina dello sviluppatore Mozilla.

Spero che abbia aiutato qualcuno.

MODIFICARE:

ES2017 includerà Object.entriesche renderà [key, value]ancora più semplice l' iterazione su coppie negli oggetti. Ora è noto che farà parte di uno standard secondo ts39 informazioni stadio .

Penso che sia tempo di aggiornare la mia risposta per renderla ancora più fresca di quanto non sia ora.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Puoi trovare ulteriori informazioni sull'utilizzo nella pagina MDN


Questo mi sembra del tutto superfluo / non necessario. Lo aggiungeresti ad ogni oggetto nel tuo sistema? Pensavo che il punto di fornire un iteratore fosse che tu potessi fare "for (const [k, v] of myObject)". Sembra solo un codice aggiuntivo che fornisce un piccolo valore aggiuntivo.
Dean Radcliffe,

22
for(key in p) {
  alert( p[key] );
}

Nota: è possibile eseguire questa operazione su array, ma si eseguirà l'iterazione anche su lengthe altre proprietà.


4
Quando si utilizza un ciclo for in questo modo, keyassumerà semplicemente un valore di indice, quindi avviserà solo 0, 1, 2, ecc ... È necessario accedere a p [chiave].
Bryan,

1
È il metodo più lento di iterazione di array in JavaScript. Puoi verificarlo sul tuo computer - Il modo migliore per scorrere su array in JavaScript
Pencroff

5
@Pencroff: il problema è che la domanda non riguarda il looping degli array ...;)
Sk8erPeter

Questo è qualcosa che non capisco su StackOverflow. Richard ha dato la risposta corretta, ed è stato il primo a dare quella risposta, ma non ha ricevuto +1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }sta spuntando "p1" e "p2" negli avvisi, quindi cosa c'è che non va ???
Sebastian,

5
Penso che la differenza principale sia la qualità: le altre risposte non solo dicono come, ma raccontano anche le avvertenze (ad esempio il prototipo) e come gestirle. IMHO, quelle altre risposte sono migliori delle mie :).
Richard Levasseur,

20

Dopo aver esaminato tutte le risposte qui, hasOwnProperty non è necessario per il mio uso perché il mio oggetto json è pulito; non ha davvero senso aggiungere ulteriori elaborazioni javascript. Questo è tutto ciò che sto usando:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

18
Se l'oggetto JSON è pulito o meno è irrilevante. Se in qualsiasi altro momento un codice imposta una proprietà su Object.prototype, allora verrà enumerata da for..in. Se sei sicuro di non utilizzare librerie che lo fanno, non è necessario chiamare hasOwnProperty.
G-Wiz,

4
Può essere completamente pulito se creato conObject.create(null)
Juan Mendes,

20

tramite prototipo con forEach () che dovrebbe saltare le proprietà della catena prototipo :

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3

2
Fai attenzione al prototipo: obj = { print: 1, each: 2, word: 3 }produce TypeError: number is not a function. L'uso forEachper abbinare la Arrayfunzione simile può ridurre leggermente il rischio.
David Harkness,

18

È interessante che le persone in queste risposte abbiano toccato entrambi Object.keys()e for...ofnon li abbiano mai combinati:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Non si può solo for...ofuna Objectperché non è un iteratore, e for...indexo .forEach()ing l' Object.keys()è brutto / inefficiente.
Sono contento che la maggior parte delle persone si stia trattenendo for...in(con o senza controllo .hasOwnProperty()) dato che è anche un po 'disordinato, quindi a parte la mia risposta sopra, sono qui per dire ...


Puoi far iterare le associazioni di oggetti ordinari! Comportarsi come una Maps con l'uso diretto della fantastica for...of
DEMO che funziona in Chrome e FF (presumo solo ES6)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Finché includi il mio spessore di seguito:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Senza dover creare un vero oggetto Map che non abbia il simpatico zucchero sintattico.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

In effetti, con questo spessore, se volevi ancora sfruttare le altre funzionalità di Map (senza metterle tutte in risalto) ma volevi comunque usare la notazione dell'oggetto ordinata, dal momento che gli oggetti sono ora iterabili, ora puoi semplicemente creare una Mappa da esso!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Per coloro a cui non piace lo shim o il pasticcio prototypein generale, sentitevi liberi di rendere la funzione sulla finestra invece, chiamandola così getObjIterator();

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

Ora puoi semplicemente chiamarlo come una normale funzione, nient'altro è interessato

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

o

for (let pair of getObjIterator(ordinaryObject))

Non c'è motivo per cui ciò non funzioni.

Benvenuti nel futuro


1
Caso in questione . Finché le persone scorrono verso il basso e lo trovano utile, questo è tutto ciò che conta. Di solito sono io che cerco di fare qualcosa, non mi piace la roba che vedo online, finisco per capirlo, poi torno a condividere. È un ottimo documento, in realtà ho trovato le mie risposte prima di cercare su google cose di cui mi ero completamente dimenticato!
Hashbrown,

@HelpMeStackOverflowMyOnlyHope Personalmente non mi piace modificare i prototipi di oggetti che non mi sono definito.
Janus Troelsen,

@JanusTroelsen hai persino letto l'intera risposta? For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
Hashbrown,

Nota che questa tecnica non funziona su oggetti semplici, ma utile comunque.
noɥʇʎԀʎzɐɹƆ

funziona per oggetti semplici, questo è letteralmente il punto centrale (così come i nomi delle variabili come ordinaryObjectper sottolineare che la magia funziona ancora per quei tipi). Hai controllato le demo? cosa non funziona per te, @ noɥʇʎԀʎzɐɹƆ? (PS la tua immagine del profilo SE è boss)
Hashbrown,

13

Object.keys (obj): Array

recupera tutte le chiavi con valori di stringa di tutte le proprietà proprie (non ereditate) enumerabili.

Quindi fornisce lo stesso elenco di chiavi che si intende testando ogni chiave di oggetto con hasOwnProperty. Non è necessaria l'operazione di test aggiuntiva rispetto a quella che Object.keys( obj ).forEach(function( key ){})dovrebbe essere più veloce. Dimostriamolo:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

Nel mio Firefox ho i seguenti risultati

  • L'approccio Object.keys ha richiesto 40.21101451665163 millisecondi.
  • per ... in / hasOwnProperty l'approccio ha richiesto 98.26163508463651 millisecondi.

PS. su Chrome la differenza è ancora maggiore http://codepen.io/dsheiko/pen/JdrqXa

PS2: In ES6 (EcmaScript 2015) puoi iterare oggetti iterabili più belli:

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});


se non hai voglia di lasciare andare la notazione {}, puoi comunque usare of senza creare Maps
Hashbrown,

13

Ecco un altro metodo per iterare attraverso un oggetto.

   var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};


Object.keys(p).forEach(key => { console.log(key, p[key]) })


3
Questo è piuttosto interessante, tuttavia per oggetti di grandi dimensioni, il formetodo potrebbe essere più performante.
Rolf

13

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>


12

Puoi anche usare Object.keys () e scorrere le chiavi dell'oggetto come di seguito per ottenere il valore:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});


Mi hai risparmiato tempo, grazie
Swap-IOS-Android,

Felice di sapere :)
Onera,

8

Solo codice JavaScript senza dipendenze:

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]

for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}

8

Il Object.keys()metodo restituisce una matrice delle proprietà enumerabili di un determinato oggetto. Leggi di più qui

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))


8

Prestazione

Oggi 2020.03.06 eseguo test delle soluzioni scelte su Chrome v80.0, Safari v13.0.5 e Firefox 73.0.1 su MacOs High Sierra v10.13.6

conclusioni

  • le soluzioni basate su for-in(A, B) sono veloci (o più veloci) per tutti i browser per oggetti grandi e piccoli
  • sorprendentemente for-of(H) la soluzione è veloce su Chrome per oggetti piccoli e grandi
  • le soluzioni basate sull'indice esplicito i(J, K) sono abbastanza veloci su tutti i browser per piccoli oggetti (per firefox veloce anche per oggetti di grandi dimensioni ma medio veloce su altri browser)
  • le soluzioni basate su iteratori (D, E) sono più lente e sconsigliate
  • la soluzione C è lenta per oggetti di grandi dimensioni e medio-lenta per oggetti di piccole dimensioni

inserisci qui la descrizione dell'immagine

Dettagli

Sono stati eseguiti test delle prestazioni per

  • piccolo oggetto - con 3 campi - puoi eseguire il test sulla tua macchina QUI
  • oggetto 'grande' - con 1000 campi - puoi eseguire test QUI sulla tua macchina

Di seguito i frammenti presenta le soluzioni utilizzate

E qui ci sono risultati per piccoli oggetti su Chrome

inserisci qui la descrizione dell'immagine


7

È possibile aggiungere un semplice forEach funzione per tutti gli oggetti, in modo da poter ciclo automaticamente attraverso qualsiasi oggetto:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

Per quelle persone a cui non piace il metodo " for ... in ":

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

Ora puoi semplicemente chiamare:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

Se non vuoi avere conflitti con altri per ogni metodo, puoi nominarlo con il tuo nome univoco.


3
La modifica dei prototipi di oggetti incorporati (come Object) è generalmente considerata un modello anti poiché può facilmente causare conflitti con altri codici. Quindi la ferita non consiglia di farlo in questo modo.
Moritz,

6

I loop possono essere piuttosto interessanti quando si utilizza JavaScript puro. Sembra che solo ECMA6 (nuova specifica JavaScript 2015) abbia controllato i loop. Sfortunatamente mentre scrivo questo, sia i Browser che il popolare ambiente di sviluppo integrato (IDE) stanno ancora lottando per supportare completamente le nuove campane e fischietti.

A colpo d'occhio ecco come appare un loop di oggetti JavaScript prima di ECMA6:

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

Inoltre, so che questo non rientra nell'ambito di questa domanda, ma nel 2011 ECMAScript 5.1 ha aggiunto il forEachmetodo solo per gli array, che fondamentalmente ha creato un nuovo modo migliorato per eseguire il loop degli array, lasciando comunque oggetti non ripetibili con il vecchio forloop dettagliato e confuso . Ma la parte strana è che questo nuovo forEachmetodo non supportabreak che ha portato a tutti i tipi di altri problemi.

Fondamentalmente nel 2011, non esiste un modo veramente solido per eseguire il ciclo in JavaScript diverso da quello che molte librerie popolari (jQuery, Underscore, ecc.) Hanno deciso di reimplementare.

A partire dal 2015, ora abbiamo un modo migliore per eseguire in loop (e interrompere) qualsiasi tipo di oggetto (inclusi array e stringhe). Ecco come apparirà un loop in JavaScript quando la raccomandazione diventerà mainstream:

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

Nota che la maggior parte dei browser non supporterà il codice sopra dal 18 giugno 2016. Anche in Chrome devi abilitare questo flag speciale per farlo funzionare: chrome://flags/#enable-javascript-harmony

Fino a quando questo non diventerà il nuovo standard, il vecchio metodo può ancora essere usato, ma ci sono anche alternative nelle librerie popolari o anche alternative leggere per coloro che non usano nessuna di queste librerie.


Potresti fornire un violino di questo lavoro? Ecco il mio tentativo. jsfiddle.net/abalter/sceeb211
abalter

@abalter Siamo spiacenti di aver realizzato un errore di battitura nel mio codice. L'ho corretto e aggiornato il tuo JsFiddle qui: jsfiddle.net/sceeb211/2
Nicolas Bouvrette,

Sono in cromo e sto ottenendo Uncaught TypeError: Object.entries is not a function. Non è ancora implementato in Chrome?
abalter,

@abalter Lo è. Assicurati di avere Chrome versione 51 e di aver abilitato il flag come spiegato nei miei commenti di modifica e Jsfiddle. Puoi controllare i dettagli qui: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette,

Mi dispiace che mi sia perso la bandiera. Vedo che non è ancora una funzionalità completamente implementata.
abalter

5

In ES6 abbiamo simboli ben noti per esporre alcuni metodi precedentemente interni, puoi usarlo per definire come funzionano gli iteratori per questo oggetto:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

questo darà lo stesso risultato dell'uso di for ... nel ciclo es6.

for(var key in p) {
    console.log(key);
}

Ma è importante conoscere le capacità che hai ora usando es6!


1
Un iteratore di oggetti personalizzati chiama l'iteratore di array incorporato di un array generato Object.keys()e allocato in memoria ... Fantastico!
ooo,

5

Vorrei fare questo invece di controllare obj.hasOwnerPropertyall'interno di ogni for ... inciclo.

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}

5

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}


json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }
Marek Bernád,

5

Usando un for-ofonObject.keys()

Piace:

let object = {
   "key1": "value1"
   "key2": "value2"
   "key3": "value3"
};

for (var key of Object.keys(p)) {
   console.log(key + " : " + object[key])
}

4

Se si desidera scorrere anche su proprietà non enumerabili , è possibile utilizzare Object.getOwnPropertyNames(obj)per restituire un array di tutte le proprietà (enumerabili o meno) trovate direttamente su un determinato oggetto.

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

obj.foo = 1; // enumerable property

Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});


2
È fantastico, grazie per aver pubblicato questa risposta. Avevo bisogno di introspettare un Erroroggetto e non potevo accedere alle proprietà in un ciclo o in una _.forIn(err)chiamata. L'utilizzo Object.getOwnPropertyNames(err)mi ha permesso di accedere a tutte le parti di Errorcui non potevo accedere prima. Grazie!
Pierce,

4

Se qualcuno ha bisogno di passare in rassegna arrayObjects con condizione :

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}


4

Considerando ES6, vorrei aggiungere il mio cucchiaio di zucchero e fornire un ulteriore approccio per scorrere le proprietà dell'oggetto.

Dal momento che il semplice oggetto JS non è iterabile appena pronto , non siamo in grado di usare il for..ofciclo per iterare sul suo contenuto. Ma nessuno può fermarci per renderlo iterabile .

Facciamo bookoggetto.

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

Da quando l'abbiamo realizzato, possiamo usarlo in questo modo:

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

O se conosci la potenza dei generatori ES6 , puoi sicuramente rendere il codice molto più breve.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

Certo, puoi applicare tale comportamento per tutti gli oggetti rendendolo Objectiterabile a prototypelivello.

Object.prototype[Symbol.iterator] = function() {...}

Inoltre, gli oggetti conformi al protocollo iterabile possono essere utilizzati con il nuovo operatore di diffusione delle funzioni ES2015 in modo da poter leggere i valori delle proprietà degli oggetti come un array.

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

Oppure puoi usare l' incarico di destrutturazione :

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

Puoi dare un'occhiata a JSFiddle con tutto il codice che ho fornito sopra.


Ho scoperto che il codice genererà i valori ma senza chiavi. È possibile iterare i valori con le chiavi?
Pika,

Si, puoi. Restituisce semplicemente "yield [chiave, obj [chiave]];" dalla tua funzione generatore e poi
usalo

4

da ES06 è possibile ottenere i valori di un oggetto come array con

let arrValues = Object.values( yourObject) ;

restituisce un array di valori oggetto e non estrae valori da Prototype !!

MDN DOCS Object.values ​​()

e per le chiavi (già risposto prima di me qui)

let arrKeys   = Object.keys(yourObject);

Le risposte richiedono una soluzione che restituisca sia chiavi che valori.
Sean Lindo,

4

Nell'ultimo script ES, puoi fare qualcosa del genere:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, 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.