Se esiste un oggetto Javascript:
var objects={...};
Supponiamo che abbia più di 50 proprietà, senza conoscere i nomi delle proprietà (ovvero senza conoscere le 'chiavi') come ottenere ogni valore di proprietà in un ciclo?
Se esiste un oggetto Javascript:
var objects={...};
Supponiamo che abbia più di 50 proprietà, senza conoscere i nomi delle proprietà (ovvero senza conoscere le 'chiavi') come ottenere ogni valore di proprietà in un ciclo?
Risposte:
Utilizzando un semplice for..in
ciclo:
for(var key in objects) {
var value = objects[key];
}
enumerable
flag impostato su false. Questo - tra le altre cose - significa che non ripeterai i metodi di classe, ma ripeterai i metodi creati in altri modi.
A seconda di quali browser devi supportare, questo può essere fatto in diversi modi. La stragrande maggioranza dei browser nel selvaggio supporta ECMAScript 5 (ES5), ma attenzione che molti degli esempi seguenti usano Object.keys
, che non è disponibile in IE <9. Vedi la tabella di compatibilità .
Se devi supportare versioni precedenti di IE, questa è l'opzione che fa per te:
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var val = obj[key];
// use val
}
}
Il nidificato if
fa in modo di non enumerare le proprietà nella catena di prototipi dell'oggetto (che è il comportamento che quasi sicuramente desideri). Devi usare
Object.prototype.hasOwnProperty.call(obj, key) // ok
piuttosto che
obj.hasOwnProperty(key) // bad
perché ECMAScript 5+ ti consente di creare oggetti senza prototipo Object.create(null)
e questi oggetti non avranno il hasOwnProperty
metodo. Il codice cattivo potrebbe anche produrre oggetti che sovrascrivono il hasOwnProperty
metodo.
È possibile utilizzare questi metodi in qualsiasi browser che supporti ECMAScript 5 e versioni successive. Questi ottengono valori da un oggetto ed evitano di enumerare la catena di prototipi. Dov'è il obj
tuo oggetto:
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var val = obj[keys[i]];
// use val
}
Se vuoi qualcosa di un po 'più compatto o vuoi stare attento con le funzioni nei loop, allora Array.prototype.forEach
è tuo amico:
Object.keys(obj).forEach(function (key) {
var val = obj[key];
// use val
});
Il metodo successivo crea un array contenente i valori di un oggetto. Questo è comodo per il looping.
var vals = Object.keys(obj).map(function (key) {
return obj[key];
});
// use vals array
Se vuoi rendere Object.keys
sicuri quelli che usano contro null
(così com'è for-in
), allora puoi farlo Object.keys(obj || {})...
.
Object.keys
restituisce proprietà enumerabili . Per iterare su oggetti semplici, questo di solito è sufficiente. Se hai qualcosa con proprietà non enumerabili con cui devi lavorare, puoi usare Object.getOwnPropertyNames
al posto di Object.keys
.
Le matrici sono più facili da ripetere con ECMAScript 2015. Puoi utilizzarlo a tuo vantaggio quando lavori con i valori uno a uno in un ciclo:
for (const key of Object.keys(obj)) {
const val = obj[key];
// use val
}
Utilizzando le funzioni fat-arrow di ECMAScript 2015, la mappatura dell'oggetto su una matrice di valori diventa una riga:
const vals = Object.keys(obj).map(key => obj[key]);
// use vals array
ECMAScript 2015 introduce Symbol
, le cui istanze possono essere utilizzate come nomi di proprietà. Per ottenere i simboli di un oggetto da enumerare, utilizzare Object.getOwnPropertySymbols
(questa funzione è il motivo per cui Symbol
non può essere utilizzata per creare proprietà private). Reflect
Fornisce la nuova API di ECMAScript 2015 Reflect.ownKeys
, che restituisce un elenco di nomi di proprietà (compresi quelli non enumerabili) e simboli.
Le comprensioni dell'array sono state rimosse da ECMAScript 6 prima della pubblicazione. Prima della loro rimozione, una soluzione sarebbe stata simile a:
const vals = [for (key of Object.keys(obj)) obj[key]];
// use vals array
ECMAScript 2016 aggiunge funzionalità che non incidono su questo argomento. La specifica ECMAScript 2017 aggiunge Object.values
e Object.entries
. Entrambi restituiscono gli array (il che sarà sorprendente per alcuni data l'analogia con Array.entries
). Object.values
può essere usato così com'è o con un for-of
ciclo.
const values = Object.values(obj);
// use values array or:
for (const val of Object.values(obj)) {
// use val
}
Se vuoi usare sia la chiave che il valore, allora Object.entries
è per te. Produce una matrice piena di [key, value]
coppie. Puoi usarlo così com'è, oppure (nota anche il compito di destrutturazione di ECMAScript 2015) in un for-of
ciclo:
for (const [key, val] of Object.entries(obj)) {
// use key and val
}
Object.values
shimInfine, come notato nei commenti e da teh_senaus in un'altra risposta, può valere la pena usarne uno come shim. Non preoccuparti, il seguente non modifica il prototipo, ma aggiunge semplicemente un metodo Object
(che è molto meno pericoloso). Usando le funzioni fat-arrow, questo può essere fatto anche in una riga:
Object.values = obj => Object.keys(obj).map(key => obj[key]);
che ora puoi usare come
// ['one', 'two', 'three']
var values = Object.values({ a: 'one', b: 'two', c: 'three' });
Se vuoi evitare lo shimmer quando Object.values
esiste un nativo , puoi fare:
Object.values = Object.values || (obj => Object.keys(obj).map(key => obj[key]));
Sii consapevole dei browser / versioni che devi supportare. Quanto sopra è corretto dove sono implementati i metodi o le funzionalità del linguaggio. Ad esempio, il supporto per ECMAScript 2015 è stato disattivato per impostazione predefinita in V8 fino a poco tempo fa, che alimentava browser come Chrome. Le funzionalità di ECMAScript 2015 devono essere evitate fino a quando i browser che si intende supportare implementano le funzionalità necessarie. Se usi babel per compilare il tuo codice in ECMAScript 5, hai accesso a tutte le funzionalità di questa risposta.
obj
due volte. Immagino che la creazione di una funzione di supporto sia inevitabile? Qualcosa di simile ai valori (obj).
Object.values = obj => Object.keys(obj).map(key => obj[key]);
Ecco una funzione riutilizzabile per ottenere i valori in un array. Prende in considerazione anche i prototipi.
Object.values = function (obj) {
var vals = [];
for( var key in obj ) {
if ( obj.hasOwnProperty(key) ) {
vals.push(obj[key]);
}
}
return vals;
}
Object
non è un grosso problema ( Object.keys
è uno shim comune), probabilmente stai pensando di modificare il prototipo Object.
hasOwnProperty()
? In che modo la chiave sarebbe ripetuta all'interno del ciclo di quell'oggetto non ha la proprietà?
Se hai accesso a Underscore.js, puoi utilizzare la _.values
funzione in questo modo:
_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]
Se vuoi davvero un array di valori, lo trovo più pulito rispetto alla creazione di un array con un ciclo for ... in.
ECMA 5.1+
function values(o) { return Object.keys(o).map(function(k){return o[k]}) }
Vale la pena notare che nella maggior parte dei casi non è davvero necessario un array di valori, sarà più veloce farlo:
for(var k in o) something(o[k]);
Ciò scorre sulle chiavi dell'oggetto o. In ogni iterazione k è impostato su una chiave di o.
ES5 Object.keys
var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]
Per quelle persone che si adeguano presto all'era di CofeeScript, ecco un altro equivalente per questo.
val for key,val of objects
Quale potrebbe essere migliore di questo perché objects
può essere ridotto per essere nuovamente digitato e ridotta leggibilità.
objects[key] for key of objects
ECMA2017 in poi:
Object.values(obj)
recupererà tutti i valori delle proprietà come un array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values
Apparentemente - come ho appreso di recente - questo è il modo più veloce per farlo:
var objs = {...};
var objKeys = Object.keys(obj);
for (var i = 0, objLen = objKeys.length; i < objLen; i++) {
// do whatever in here
var obj = objs[objKeys[i]];
}
La domanda non specifica se si desidera anche proprietà ereditate e non enumerabili.
C'è una domanda per ottenere tutto, proprietà ereditate e anche proprietà non enumerabili , che Google non riesce a trovare facilmente.
La mia soluzione per questo è:
function getAllPropertyNames(obj) {
let result = new Set();
while (obj) {
Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
obj = Object.getPrototypeOf(obj);
}
return [...result];
}
E quindi scorrere su di essi, basta usare un ciclo for-of:
Usa Object.values()
:, passiamo un oggetto come argomento e riceviamo una matrice di valori come valore di ritorno.
Ciò restituisce una matrice di valori di proprietà enumerabili propri di un determinato oggetto. Otterrai gli stessi valori utilizzando il for in
ciclo ma senza le proprietà sul prototipo. Questo esempio probabilmente renderà le cose più chiare:
function person (name) {
this.name = name;
}
person.prototype.age = 5;
let dude = new person('dude');
for(let prop in dude) {
console.log(dude[prop]); // for in still shows age because this is on the prototype
} // we can use hasOwnProperty but this is not very elegant
// ES6 +
console.log(Object.values(dude));
// very concise and we don't show props on prototype
Ecco una funzione simile a array_values () di PHP
function array_values(input) {
var output = [], key = '';
for ( key in input ) { output[output.length] = input[key]; }
return output;
}
Ecco come ottenere i valori dell'oggetto se si utilizza ES6 o versione successiva:
Array.from(values(obj));
Da allora, Object.values(<object>)
sarà integrato in ES7 e
Fino ad attendere che tutti i browser lo supportino, è possibile inserirlo in una funzione:
Object.vals=(o)=>(Object.values)?Object.values(o):Object.keys(o).map((k)=>o[k])
Poi :
Object.vals({lastname:'T',firstname:'A'})
// ['T','A']
Object.entries lo fa in modo migliore.
var dataObject = {"a":{"title":"shop"}, "b":{"title":"home"}}
Object.entries(dataObject).map(itemArray => {
console.log("key=", itemArray[0], "value=", itemArray[1])
})
const myObj = { a:1, b:2, c:3 }
Ottieni tutti i valori:
il modo più breve:
const myValues = Object.values(myObj)
const myValues = Object.keys(myObj).map(key => myObj[key])
in ECMAScript5 uso
keys = Object.keys(object);
Altrimenti se il tuo browser non lo supporta, usa il noto for..in loop
for (key in object) {
// your code here
}
object[key]
per ottenere i valori in un ciclo.
for..in
(e hasOwnProperty) in modo che non ottenga davvero nulla .. Vorrei che ECMAScript 5th fosse definito Object.pairs
(e Object.items
per [[key, value], ..]
), ma purtroppo non lo è.
Ora uso Dojo Toolkit perché i browser più vecchi non supportano Object.values
.
require(['dojox/lang/functional/object'], function(Object) {
var obj = { key1: '1', key2: '2', key3: '3' };
var values = Object.values(obj);
console.log(values);
});
Produzione :
['1', '2', '3']