Wie liste ich die Eigenschaften eines JavaScript-Objekts auf?

842

Angenommen, ich erstelle ein Objekt folgendermaßen:

var myObject =
        {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

Was ist der beste Weg, um eine Liste der Eigenschaftsnamen abzurufen? dh ich möchte am Ende einige variable 'Schlüssel' haben, so dass:

keys == ["ircEvent", "method", "regex"]
Johnstok
quelle
3
Ein bisschen vom Thema ab, aber wenn Sie underscore.js verwenden:_.keys(myJSONObject)
Endy Tjahjono

Antworten:

1076

In modernen Browsern (IE9 +, FF4 +, Chrome5 +, Opera12 +, Safari5 +) können Sie die integrierte Object.keys- Methode verwenden:

var keys = Object.keys(myObject);

Das obige hat eine vollständige Polyfüllung, aber eine vereinfachte Version ist:

var getKeys = function(obj){
   var keys = [];
   for(var key in obj){
      keys.push(key);
   }
   return keys;
}

Ersetzen Alternativ var getKeysmit Object.prototype.keys, damit Sie rufen .keys()auf ein beliebiges Objekt. Das Erweitern des Prototyps hat einige Nebenwirkungen, und ich würde es nicht empfehlen.

Slashnick
quelle
17
Ich würde erneut auf den Effekt aktualisieren: "Sie könnten versucht sein, dies zu tun, um den Prototyp zu objektieren ... aber nicht!"
AnthonyWJones
4
Möchte jemand Licht ins Dunkel bringen, warum wird nicht empfohlen, dem Prototyp des Objekts Funktionen hinzuzufügen?
Vishwanath
2
Das ist eine ganz andere Frage für sich. Eine schnelle Suche hier auf stackoverflow oder auf Google gibt Ihnen viel zu lesen
ximi
3
Die for (var key in myObject) {...}Technik ist nützlich für Javascript-Laufzeiten außerhalb von Browsern und V8. Wenn Sie beispielsweise JavaScript-Map-Reduce-Abfragen an Riak übergeben, ist das ObjectObjekt nicht vorhanden, sodass die Object.keysMethode nicht verfügbar ist.
Ekillaby
19
@slashnick Ihre "vereinfachte Version" gibt alle Eigenschaften in der Prototypkette des Objekts zurück (da ein "for ... in" verwendet wird), während die Object.keysMethode (ECMAScript 5.1) nur die eigenen Eigenschaften des Objekts zurückgibt. Ich sehe es als wichtige Unterscheidung.
Martin Carel
255

Wie slashnick betonte, können Sie das Konstrukt "for in" verwenden, um ein Objekt nach seinen Attributnamen zu durchsuchen. Sie werden jedoch alle Attributnamen in der Prototypenkette des Objekts durchlaufen. Wenn Sie nur über die eigenen Attribute des Objekts iterieren möchten , können Sie die Methode Object # hasOwnProperty () verwenden. Also mit folgendem.

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        /* useful code here */
    }
}
Pablo Cabrera
quelle
25
Ich wünschte, ich hätte dies vor Slashnics Antwort oben gelesen. Ich musste nur 15 Minuten damit verbringen, den escSchlüssel gedrückt zu halten, da das Objekt ungefähr eine Million Eigenschaften hatte, von denen die meisten nicht verwendet wurden, und ich hatte eine Warnung darauf.
Mark Henderson
Hier ist ein ausgezeichneter Artikel zu diesem Thema von Zakas selbst: nczonline.net/blog/2010/07/27/…
Pablo Cabrera
4
LOL @MarkHenderson - aber beim nächsten Mal einfach den Prozess des Browsers beenden und neu starten, anstatt 15 Minuten zu verschwenden :)
JD Smith
Eine verwandte Funktion ist obj.getOwnPropertyNames () - developer.mozilla.org/en-US/docs/JavaScript/Reference/…
Steve Goodman
@ MarkHenderson Warum verwenden Sie console.log nicht?
LasagneAndroid
102

Wie Sam Dutton antwortete, wurde in ECMAScript 5th Edition eine neue Methode für diesen Zweck eingeführt. Object.keys()macht, was Sie wollen und wird in Firefox 4 , Chrome 6, Safari 5 und IE 9 unterstützt .

Sie können die Methode auch sehr einfach in Browsern implementieren, die sie nicht unterstützen. Einige der Implementierungen sind jedoch nicht vollständig mit Internet Explorer kompatibel. Hier ist eine kompatiblere Lösung:

Object.keys = Object.keys || (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
        DontEnums = [ 
            'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
            'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
        ],
        DontEnumsLength = DontEnums.length;

    return function (o) {
        if (typeof o != "object" && typeof o != "function" || o === null)
            throw new TypeError("Object.keys called on a non-object");

        var result = [];
        for (var name in o) {
            if (hasOwnProperty.call(o, name))
                result.push(name);
        }

        if (hasDontEnumBug) {
            for (var i = 0; i < DontEnumsLength; i++) {
                if (hasOwnProperty.call(o, DontEnums[i]))
                    result.push(DontEnums[i]);
            }   
        }

        return result;
    };
})();

Beachten Sie, dass die aktuell akzeptierte Antwort keine Prüfung auf hasOwnProperty () enthält und Eigenschaften zurückgibt , die über die Prototypenkette vererbt werden. Der berühmte DontEnum-Fehler in Internet Explorer, bei dem nicht aufzählbare Eigenschaften in der Prototypenkette dazu führen, dass lokal deklarierte Eigenschaften mit demselben Namen ihr DontEnum-Attribut erben, wird ebenfalls nicht berücksichtigt.

Durch die Implementierung von Object.keys () erhalten Sie eine robustere Lösung.

BEARBEITEN: Nach einer kürzlichen Diskussion mit kangax , einem bekannten Mitwirkenden an Prototype, habe ich die Problemumgehung für den DontEnum-Fehler basierend auf dem Code für seine hierObject.forIn() gefundene Funktion implementiert .

Andy E.
quelle
Tolle Antwort, ich denke, die akzeptierte Antwort bleibt die performanteste und genaueste Lösung, vorausgesetzt, es handelt sich immer um ein JSON-Diktat. Dies ist sicherlich derjenige, der anderswo verwendet werden kann.
David Snabel-Caunt
1
@ David Caunt: Danke :-) Leider würde die akzeptierte Antwort immer noch den DontEnum-Fehler verfehlen und Sie wissen nie, welches JSON-Objekt eine Zeichenfolge wie "valueOf" oder "constructor" als einen seiner Schlüssel haben könnte. Es wird auch über Erweiterungen zu iterieren Object.prototype. Es ist jedoch häufig der Fall, dass kürzerer Code wesentlich ansprechender aussieht als größerer, robusterer Code. Bei dieser Antwort geht es jedoch darum, ECMAScript 5ths zu verwenden Object.keys(), die in Browsern implementiert werden können, die ihn mit diesem Code nicht unterstützen. Die native Version wäre noch performanter.
Andy E
2
Sehr nett, Andy :) Ich möchte nur daran erinnern - niemand scheint in diesem Thread zu erwähnen -, dass ES5 Object.keysnur ein Array von Zeichenfolgen zurückgibt, die den aufzählbaren Eigenschaften eines Objekts entsprechen. Dies ist möglicherweise nicht entscheidend, wenn Sie mit nativen (benutzerdefinierten) Objekten arbeiten, sollte jedoch bei Hostobjekten sehr gut sichtbar sein (obwohl das Verhalten nicht spezifizierter Hostobjekte eine separate - schmerzhafte - Geschichte ist). Um ALLE (einschließlich nicht aufzählbarer) Eigenschaften aufzulisten, bietet ES5 Object.getOwnPropertyNames(siehe seine Unterstützung in meiner kompatiblen Tabelle - kangax.github.com/es5-compat-table )
kangax
2
Ich habe diese Lösung in es5-shim github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L390
Kris Kowal
2
Kann jemand erklären, warum dies so implementiert ist Object.keys(stuff)und nicht stuff.keys()?
Blazemonger
32

Beachten Sie, dass Object.keys und andere ECMAScript 5-Methoden von Firefox 4, Chrome 6, Safari 5, IE 9 und höher unterstützt werden.

Zum Beispiel:

var o = {"foo": 1, "bar": 2}; 
alert(Object.keys(o));

ECMAScript 5-Kompatibilitätstabelle: http://kangax.github.com/es5-compat-table/

Beschreibung neuer Methoden: http://markcaudill.com/index.php/2009/04/javascript-new-features-ecma5/

Sam Dutton
quelle
Überprüfen Sie auch Schlüssel () in der Konsole für Chrome Dev Tools, Firebug usw.
Sam Dutton
28

Object.getOwnPropertyNames(obj)

Diese Funktion zeigt zusätzlich zu den von gezeigten auch nicht aufzählbare Eigenschaften an Object.keys(obj).

In JS verfügt jede Eigenschaft über einige Eigenschaften, einschließlich eines Booleschen Werts enumerable.

Im Allgemeinen sind nicht aufzählbare Eigenschaften "interner" und werden seltener verwendet, aber es ist aufschlussreich, sie manchmal zu untersuchen, um zu sehen, was wirklich vor sich geht.

Beispiel:

var o = Object.create({base:0})
Object.defineProperty(o, 'yes', {enumerable: true})
Object.defineProperty(o, 'not', {enumerable: false})

console.log(Object.getOwnPropertyNames(o))
// [ 'yes', 'not' ]

console.log(Object.keys(o))
// [ 'yes' ]

for (var x in o)
    console.log(x)
// yes, base

Beachten Sie auch, wie:

  • Object.getOwnPropertyNamesund Object.keys gehen Sie nicht die Prototypenkette hinauf, um zu findenbase
  • for in tut

Weitere Informationen zur Prototypenkette finden Sie hier: https://stackoverflow.com/a/23877420/895245

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
quelle
16

Ich bin ein großer Fan der Dump-Funktion.

http://ajaxian.com/archives/javascript-variable-dump-in-coldfusion Alt-Text

Matt
quelle
1
+1, weil ich hierher gekommen bin, um etwas Ähnliches zu bauen (wenn auch nicht so gut).
Camilo Martin
1
netgrow.com.au/assets/files/dump/dump.zip nicht gefunden Wie kann ich Dump-Javascript herunterladen?
Kiquenet
@Kiquenet Jedes Mal, wenn ich so etwas erstellen wollte, entscheide ich mich für den regulären Objektinspektor. Wenn Sie möchten, dass das in HTML gerendert wird, gibt es Dinge wie npm-Module . Ehrlich gesagt, was mich feststeckte, war, dass ich etwas Besseres wollte als das, was auf diesem Bild steht, aber es nie geschafft habe, es zu konzipieren. Es ist beschissen, Objekte im Inspektor zu durchsuchen, aber Heuristiken, um zu versuchen, aus beliebigen Objekten eine Bedeutung abzuleiten (z. B. Arrays von Objekten in Tabellen mit Spalten zu sortieren), funktionieren in der Praxis nicht immer.
Camilo Martin
Was ist mit Pretty Print Javascript https://j11y.io/demos/prettyprint/ ?
Kiquenet
13

Könnte es mit jQuery wie folgt machen:

var objectKeys = $.map(object, function(value, key) {
  return key;
});
Sbonami
quelle
9

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. "Dies" ist das Hashmap-Objekt, das die Schlüssel enthält

zeacuss
quelle
8

Dies funktioniert in den meisten Browsern, auch in IE8, und es sind keine Bibliotheken jeglicher Art erforderlich. var i ist dein Schlüssel.

var myJSONObject =  {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; 
var keys=[];
for (var i in myJSONObject ) { keys.push(i); }
alert(keys);
qwerty_jones
quelle
2
Ihre Antwort scheint den bereits veröffentlichten ähnlich zu sein. Möchten Sie noch etwas hinzufügen?
VKen
7

Unter Browsern, die js 1.8 unterstützen:

[i for(i in obj)]
Rix Beck
quelle
7

Mozilla verfügt über vollständige Implementierungsdetails zur Vorgehensweise in einem Browser, in dem dies nicht unterstützt wird. Wenn dies hilfreich ist:

if (!Object.keys) {
  Object.keys = (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;

    return function (obj) {
      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

      var result = [];

      for (var prop in obj) {
        if (hasOwnProperty.call(obj, prop)) result.push(prop);
      }

      if (hasDontEnumBug) {
        for (var i=0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
        }
      }
      return result;
    };
  })();
}

Sie können es beliebig einfügen, möglicherweise jedoch in einer extensions.jsDatei oben in Ihrem Skriptstapel.

Kristofer Sommestad
quelle
Die MDN-Implementierung basiert auf Andy E's, das bereits als Antwort gegeben wurde.
Outis
5

Verwenden Reflect.ownKeys()

var obj = {a: 1, b: 2, c: 3};
Reflect.ownKeys(obj) // ["a", "b", "c"]

Object.keys und Object.getOwnPropertyNames können keine nicht aufzählbaren Eigenschaften erhalten. Es funktioniert sogar für nicht aufzählbare Eigenschaften.

var obj = {a: 1, b: 2, c: 3};
obj[Symbol()] = 4;
Reflect.ownKeys(obj) // ["a", "b", "c", Symbol()]
Selmansamet
quelle
4

Da ich in fast jedem Projekt underscore.js verwende , würde ich folgende keysFunktion verwenden:

var obj = {name: 'gach', hello: 'world'};
console.log(_.keys(obj));

Die Ausgabe davon wird sein:

['name', 'hello']
schmijos
quelle
Es ist eine Toolset-Bibliothek für häufig verwendete Javascript-Funktionen: underscorejs.org
schmijos
4

Aufbauend auf der akzeptierten Antwort.

Wenn das Objekt Eigenschaften hat, die Sie aufrufen möchten, sagen wir .properties () try!

var keys = Object.keys(myJSONObject);

for (var j=0; j < keys.length; j++) {
  Object[keys[j]].properties();
}
Sydwell
quelle
0

Die Lösung funktioniert für meine Fälle und Cross-Browser:

var getKeys = function(obj) {
    var type = typeof  obj;
    var isObjectType = type === 'function' || type === 'object' || !!obj;

    // 1
    if(isObjectType) {
        return Object.keys(obj);
    }

    // 2
    var keys = [];
    for(var i in obj) {
        if(obj.hasOwnProperty(i)) {
            keys.push(i)
        }
    }
    if(keys.length) {
        return keys;
    }

    // 3 - bug for ie9 <
    var hasEnumbug = !{toString: null}.propertyIsEnumerable('toString');
    if(hasEnumbug) {
        var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
            'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];

        var nonEnumIdx = nonEnumerableProps.length;

        while (nonEnumIdx--) {
            var prop = nonEnumerableProps[nonEnumIdx];
            if (Object.prototype.hasOwnProperty.call(obj, prop)) {
                keys.push(prop);
            }
        }

    }

    return keys;
};
Christian Nguyen
quelle