Wie finde ich Schlüssel eines Hash?

192

Ich weiß, dass in Javascript Objekte doppelt so viele Hashes sind, aber ich konnte keine eingebaute Funktion finden, um die Schlüssel zu erhalten

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

Ich möchte so etwas wie

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

Es ist einfach, selbst eine Funktion zu schreiben, um die Elemente zu durchlaufen und die Schlüssel zu einem Array hinzuzufügen, das ich zurückgebe. Aber gibt es eine sauberere Standardmethode, um dies zu tun?

Ich habe immer das Gefühl, dass es eine einfache eingebaute Funktion sein muss, die ich verpasst habe, aber ich kann sie nicht finden!

Klopfen
quelle
Ich springe gerade in Javascript, aber dieser Beitrag kann Ihnen helfen. dean.edwards.name/weblog/2006/07/enum
jason saldo
Mögliches Duplikat von Get Array der Objektschlüssel
blo0p3r
1
Was ist mit dem Abrufen der Werte von den Schlüsseln? Außerdem wird die Anzahl der Schlüssel in einem Hash ermittelt.
zero_cool
Die Antwort 2017: Object.keys (h) Object.values ​​(h)
verloren

Antworten:

274

In modernem JavaScript (ECMAScript 5) gibt es eine Funktion, Object.keysdie diese Operation ausführt:

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

Details zur Kompatibilität finden Sie hier .

Auf der Mozilla-Site gibt es auch einen Ausschnitt zur Abwärtskompatibilität:

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;
}
Ivan Nevostruev
quelle
Wäre das nicht natürlicher gewesen? 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
Wie verstehe ich das Object.prototype.keysmacht keysfür alle Unterklassen von Object zur Verfügung, also für alle Objekte. Was Sie wahrscheinlich möchten, wenn Sie versuchen, OOP zu verwenden. Auf jeden Fall hängt dies wirklich von Ihren Anforderungen ab.
Ivan Nevostruev
1
Wenn Sie mootools verwenden, sollte Object.keys () in allen Browsern verfügbar sein.
Thepeer
Gibt es etwas, um dies in eckigen Vorlagen zu verwenden? Es funktioniert dort nicht in Teilbereichen.
Jay Shukla
Ich denke, Sie sollten dies als separate Frage mit Codebeispiel stellen.
Ivan Nevostruev
80

Für Produktionscode, der eine große Kompatibilität mit Client-Browsern erfordert, empfehle ich weiterhin Ivan Nevostruevs Antwort oben mit Shim, um dies Object.keysin älteren Browsern sicherzustellen . Mit der neuen Funktion von ECMA ist es jedoch möglich, die genaue angeforderte Funktionalität zu erhalten defineProperty.

Ab ECMAScript 5 - Object.defineProperty

Ab ECMA5 können Sie Object.defineProperty()nicht aufzählbare Eigenschaften definieren. Die aktuelle Kompatibilität lässt noch zu wünschen übrig, sollte aber irgendwann in allen Browsern verwendbar sein. (Beachten Sie insbesondere die aktuelle Inkompatibilität mit 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"]

Da ECMA5 jedoch bereits hinzugefügt wurde, können Object.keysSie auch Folgendes verwenden:

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

Ursprüngliche Antwort

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

Bearbeiten: Da es diese Antwort schon eine Weile gibt, werde ich das oben Gesagte unberührt lassen. Wer dies liest, sollte auch die Antwort von Ivan Nevostruev unten lesen.

Es gibt keine Möglichkeit, Prototypfunktionen nicht aufzählbar zu machen, was dazu führt, dass sie immer in For-In-Schleifen auftauchen, die nicht verwendet werden hasOwnProperty. Ich denke immer noch, dass diese Antwort ideal wäre, wenn die Erweiterung des Prototyps von Object nicht so chaotisch wäre.

AnnanFay
quelle
9
'hasOwnProperty' schließt Eigenschaften für die Prototypen dieses Objekts aus, was nützlich zu wissen ist.
ijw
2
Die Antwort wurde akzeptiert, da ich sie so implementiert habe, aber ich denke, dass dies eine integrierte Funktion der Sprache sein sollte.
Pat
5
Beachten Sie, dass Sie "for (var i in this) ..." verwenden sollten, um das Erstellen einer globalen Variablen zu vermeiden.
Brad G.
5
Ich würde es vermeiden, Object.prototype zu ändern. Wie ein anderer Kommentator weiter unten erwähnt, kann dies leicht dazu führen, dass Skripte beschädigt werden, bei denen die Überprüfung von hasOwnProperty () nicht sorgfältig durchgeführt wird. Verwenden Sie stattdessen die weniger OO-freundliche Methode: Definieren Sie eine Tastenfunktion, falls diese noch nicht vorhanden ist. (Firefox und Chrome implementieren beide eine native Schlüsselfunktion (), die genau das tut, was das OP will - IE nicht)
Digitalbad
1
Es scheint eine schlechte Idee zu sein, Object.prototype etwas hinzuzufügen, da es jede normale Schleife wie folgt durchbricht: for (var k im Array) {} oder for (var k im Objekt) und diese Redewendung - obwohl sie möglicherweise fehlerhaft ist - ist sehr häufig. Zum Beispiel bricht es laut Matthew Darwins Antwort unten Google Maps.
Sam Watkins
42

Sie können verwenden Object.keys

Object.keys(h)
Leticia Santos
quelle
3
In ECMAScript 5 hinzugefügt, sollte aber jetzt in den meisten gängigen Browsern funktionieren
Pat
33

Sie können Underscore.js verwenden , eine Javascript-Dienstprogrammbibliothek.

_.keys({one : 1, two : 2, three : 3}); 
// => ["one", "two", "three"]
Timotti
quelle
Nun, es ist nicht wirklich das, was gefragt wurde, weil @Pat nach einer eingebauten Funktion sucht, aber es ist trotzdem eine interessante Bibliothek, die sich nicht ändertObject.prototype
fresskoma
2
Heutzutage denke ich, dass es viel hilfreicher ist, diese raffinierten kleinen Bibliotheks-Lets zu verwenden, als weiterhin eigene Implementierungen zu schreiben ... Wie auch immer, in den meisten realen Projekten verwenden wir sowieso Unterstriche oder gleichwertige Bibliotheken. Persönlich würde ich lieber mit Unterstrich gehen.
Kumarshar
_.keys(obj).lengthum zu sehen, ob es irgendwelche Schlüssel gibt.
Chovy
13

Soweit ich weiß, ist dies das Beste, was Sie tun können ...

var keys = [];
for (var k in h)keys.push(k);
danb
quelle
2
Dies funktioniert auch nicht, wenn Object.prototype durcheinander gebracht wurde.
Phil
4
Es wäre besser, dies zu verwenden und nicht mit Object.prototype "herumzuspielen". Es scheint, dass alles kaputt geht, wenn wir Object.prototype Dinge hinzufügen: Es ist eine äußerst verbreitete Redewendung, die Schlüssel eines Arrays / Objekts zu durchlaufen.
Sam Watkins
8

Mit jQuery können Sie die Schlüssel wie folgt erhalten:

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

Oder:

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

danke an @pimlottc

chim
quelle
3
Wenn Sie diese Route gehen JQuery.map$.map(h, function(v,k) { return k; });
möchten
6

Ich glaube, Sie können die Eigenschaften des Objekts mit for / in durchlaufen, um so etwas zu tun:

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

Ich wollte die oben am besten bewertete Antwort verwenden

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

In Verbindung mit der Google Maps API v3 ist Google Maps jedoch nicht funktionsfähig.

for (var key in h) ...

funktioniert gut.

Matthew Darwin
quelle
1

Wenn Sie versuchen, nur die Elemente, aber nicht die Funktionen abzurufen, kann Ihnen dieser Code helfen

this.getKeys = function() {

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

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

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

}}

Dies ist Teil meiner Implementierung der HashMap und ich möchte nur die Schlüssel, thisist das Hashmap-Objekt, das die Schlüssel enthält

zeacuss
quelle