Come trovare le chiavi di un hash?


192

Conosco oggetti javascript doppi come hash ma non sono riuscito a trovare una funzione integrata per ottenere le chiavi

var h = {a:'b',c:'d'};

Voglio qualcosa del genere

var k = h.keys() ; // k = ['a','c'];

È semplice scrivere una funzione per scorrere gli elementi e aggiungere le chiavi a un array che restituisco, ma esiste un modo più pulito standard per farlo?

Continuo a pensare che debba essere una semplice funzione integrata che mi è sfuggita ma non riesco a trovarla!


Sto solo saltando su JavaScript ma questo post può aiutarti. dean.edwards.name/weblog/2006/07/enum
jason saldo


1
Che ne dici di ottenere i valori dalle chiavi? Inoltre, ottenere il numero di chiavi in ​​un hash.
zero_cool

La risposta del 2017: Object.keys (h) Object.values ​​(h)
losty

Risposte:


274

C'è una funzione nel moderno JavaScript (ECMAScript 5) chiamata Object.keyseseguendo questa operazione:

var obj = { "a" : 1, "b" : 2, "c" : 3};
alert(Object.keys(obj)); // will output ["a", "b", "c"]

I dettagli sulla compatibilità sono disponibili qui .

Sul sito Mozilla è presente anche uno snippet per la compatibilità con le versioni precedenti:

if(!Object.keys) Object.keys = function(o){
   if (o !== Object(o))
      throw new TypeError('Object.keys called on non-object');
   var ret=[],p;
   for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);
   return ret;
}

non sarebbe stato più naturale? if(!Object.prototype.keys) Object.prototype.keys = function() { if (this !== Object(this)) throw new TypeError('Object.keys called on non-object'); var ret = [], p; for (p in this) if (Object.prototype.hasOwnProperty.call(this, p)) ret.push(p); return ret; } var x = { a: { A: 1, B: 2, C: 3 }, b: { A: 10, B: 20 } }; alert(x.a.keys());
ekkis,

2
A quanto ho capito, questo Object.prototype.keysrenderà keysdisponibile a tutte le sottoclassi di Object, quindi per tutti gli oggetti. Che probabilmente vuoi fare se stai cercando di usare OOP. Comunque, questo dipende davvero dalle tue esigenze.
Ivan Nevostruev il

1
Se usi mootools, Object.keys () dovrebbe essere disponibile in tutti i browser.
thepeer,

C'è qualcosa da usare in questi modelli angolari? Non funziona lì dentro i parziali.
Jay Shukla,

Penso che dovresti porlo come domanda separata con un esempio di codice.
Ivan Nevostruev il

80

Per il codice di produzione che richiede una grande compatibilità con i browser client suggerisco ancora la risposta di Ivan Nevostruev sopra con lo shim per garantire Object.keysnei browser più vecchi. Tuttavia, è possibile ottenere l'esatta funzionalità richiesta utilizzando la nuova definePropertyfunzionalità ECMA .

A partire da ECMAScript 5 - Object.defineProperty

A partire da ECMA5 è possibile utilizzare Object.defineProperty()per definire proprietà non enumerabili. L' attuale compatibilità ha ancora molto da desiderare, ma alla fine dovrebbe diventare utilizzabile in tutti i browser. (Nota in particolare l'attuale incompatibilità con IE8!)

Object.defineProperty(Object.prototype, 'keys', {
  value: function keys() {
    var keys = [];
    for(var i in this) if (this.hasOwnProperty(i)) {
      keys.push(i);
    }
    return keys;
  },
  enumerable: false
});

var o = {
    'a': 1,
    'b': 2
}

for (var k in o) {
    console.log(k, o[k])
}

console.log(o.keys())

# OUTPUT
# > a 1
# > b 2
# > ["a", "b"]

Tuttavia, poiché ECMA5 ha già aggiunto, Object.keysè possibile utilizzare anche:

Object.defineProperty(Object.prototype, 'keys', {
  value: function keys() {
    return Object.keys(this);
  },
  enumerable: false
});

Risposta originale

Object.prototype.keys = function ()
{
  var keys = [];
  for(var i in this) if (this.hasOwnProperty(i))
  {
    keys.push(i);
  }
  return keys;
}

Modifica: Dal momento che questa risposta è in circolazione da un po ', lascerò intatto quanto sopra. Chiunque legga questo dovrebbe anche leggere la risposta di Ivan Nevostruev di seguito.

Non c'è modo di rendere non enumerabili le funzioni del prototipo, il che porta a farle apparire in loop for-in che non usano hasOwnProperty. Penso ancora che questa risposta sarebbe l'ideale se l'estensione del prototipo di Object non fosse così disordinata.


9
'hasOwnProperty' esclude le proprietà sui prototipi di questo oggetto, che è utile sapere.
ijw

2
Risposta accettata perché è così che ho finito per implementarlo, ma penso che questo avrebbe dovuto essere una funzione integrata del linguaggio.
Pat

5
Nota che dovresti usare "for (var i in this) ..." per evitare di creare una variabile globale.
Brad G.

5
Eviterei di modificare Object.prototype - come notato da un altro commentatore di seguito, questo può facilmente rompere gli script che non fanno attenzione a controllare hasOwnProperty (). Invece, usa il modo meno OO-friendly: definisci una funzione 'chiavi' se non esiste già. (Firefox e Chrome implementano entrambi una funzione di chiavi native () che fa esattamente ciò che l'OP vuole - IE no)
digitalbath

1
Sembra essere una cattiva idea aggiungere qualcosa a Object.prototype, poiché interrompe ogni normale ciclo come: for (var k in array) {} o for (var k in object), e quell'idioma - anche se potrebbe essere difettoso - è estremamente comune. Ad esempio, secondo la risposta di Matthew Darwin di seguito, si rompe Google Maps.
Sam Watkins,

42

Puoi usare Object.keys

Object.keys(h)

3
Aggiunto in ECMAScript 5 ma ormai dovrebbe funzionare nella maggior parte dei browser principali
Pat

33

È possibile utilizzare Underscore.js , che è una libreria di utilità Javascript.

_.keys({one : 1, two : 2, three : 3}); 
// => ["one", "two", "three"]

Bene, non è proprio quello che è stato chiesto, perché @Pat è alla ricerca di una funzione integrata, ma è comunque una libreria interessante e non si modificaObject.prototype
fresskoma

2
In questi giorni, penso che sia molto più utile usare queste piccole librerie eleganti che continuare a scrivere le tue implementazioni ... Comunque, nella maggior parte dei progetti del mondo reale, stiamo usando comunque Underscore o librerie equivalenti. Personalmente, preferirei andare con Underscore.
Kumarharsh,

_.keys(obj).lengthper vedere se ci sono delle chiavi.
Chovy

13

Questo è il meglio che puoi fare, per quanto ne so ...

var keys = [];
for (var k in h)keys.push(k);

2
Anche questo non funziona quando Object.prototype è stato incasinato.
Phil

4
Sarebbe meglio usarlo e non "confondere" con Object.prototype. Sembra che tutto si rompa se aggiungiamo cose a Object.prototype: è un linguaggio estremamente comune passare in rassegna le chiavi di un array / oggetto.
Sam Watkins,

8

usando jQuery puoi ottenere le chiavi in ​​questo modo:

var bobject =  {primary:"red",bg:"maroon",hilite:"green"};
var keys = [];
$.each(bobject, function(key,val){ keys.push(key); });
console.log(keys); // ["primary", "bg", "hilite"]

O:

var bobject =  {primary:"red",bg:"maroon",hilite:"green"};
$.map(bobject, function(v,k){return k;});

grazie a @pimlottc


3
Se vuoi seguire questa strada, potresti anche usare JQuery.map: $.map(h, function(v,k) { return k; });
pimlottc

6

Credo che puoi scorrere le proprietà dell'oggetto usando for / in, quindi potresti fare qualcosa del genere:

function getKeys(h) {
  Array keys = new Array();
  for (var key in h)
    keys.push(key);
  return keys;
}

4

Volevo usare la risposta più votata sopra

Object.prototype.keys = function () ...

Tuttavia, quando si utilizza congiuntamente all'API google maps v3, google maps non funziona.

for (var key in h) ...

funziona bene.


1

se stai cercando di ottenere solo gli elementi ma non le funzioni, questo codice può aiutarti

this.getKeys = function() {

var keys = new Array();
for(var key in this) {

    if( typeof this[key] !== 'function') {

        keys.push(key);
    }
}
return keys;

}

questo fa parte della mia implementazione di HashMap e voglio solo le chiavi, thisè l'oggetto hashmap che contiene le chiavi

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.