725 Stimmen

Wie kann ich die Eigenschaften eines JavaScript-Objekts aufzählen?

Wie kann ich die Eigenschaften eines JavaScript-Objekts aufzählen?

Eigentlich möchte ich alle definierten Variablen und ihre Werte auflisten, aber ich habe gelernt, dass das Definieren einer Variablen tatsächlich eine Eigenschaft des Fensterobjekts erzeugt.

898voto

Jason Bunting Punkte 56534

Das ist ganz einfach:

for(var propertyName in myObject) {
   // propertyName is what you want
   // you can get the value like this: myObject[propertyName]
}

Auf diese Weise erhalten Sie keine privaten Variablen, da diese nicht verfügbar sind.


EDIT: @bitwiseplatypus ist richtig, dass, wenn Sie nicht die hasOwnProperty() Methode erhalten Sie Eigenschaften, die vererbt werden - ich wüsste allerdings nicht, warum jemand, der mit objektorientierter Programmierung vertraut ist, etwas anderes erwarten sollte! Typischerweise hat jemand, der dies anspricht, Douglas Crockfords Warnungen zu hören bekommen, die mich immer noch ein wenig verwirren. Nochmals: Vererbung ist ein normaler Bestandteil von OO-Sprachen und daher auch ein Bestandteil von JavaScript, auch wenn es prototypisch ist.

Nun, das ist gesagt, hasOwnProperty() es nützlich für die Filterung, aber wir müssen keine Warnung aussprechen, als ob es etwas Gefährliches wäre, geerbte Eigenschaften zu erhalten.

EDIT 2: @bitwiseplatypus spricht die Situation an, die entstehen würde, wenn jemand Ihren Objekten zu einem späteren Zeitpunkt Eigenschaften/Methoden hinzufügt, als Sie Ihre Objekte ursprünglich geschrieben haben (über ihren Prototyp) - es stimmt zwar, dass dies zu unerwartetem Verhalten führen könnte, aber ich persönlich sehe das nicht als mein Problem an. Das ist nur eine Frage der Meinung. Außerdem, was ist, wenn ich Dinge so entwerfe, dass ich Prototypen während der Konstruktion meiner Objekte verwende und dennoch Code habe, der über die Eigenschaften des Objekts iteriert, und ich möchte alle geerbten Eigenschaften haben? Ich würde nicht hasOwnProperty() . Und dann, sagen wir mal, fügt jemand später neue Eigenschaften hinzu. Ist es meine Schuld, wenn sich die Dinge zu diesem Zeitpunkt schlecht verhalten? Nein, das glaube ich nicht. Ich denke, dass dies der Grund dafür ist, dass jQuery, als Beispiel, bestimmte Möglichkeiten zur Erweiterung seiner Funktionsweise hat (über jQuery.extend y jQuery.fn.extend ).

7 Stimmen

Ich glaube, @bitwiseplatypus will nur sagen: "Sei vorsichtig". Ich bin der Meinung, dass JavaScript's for/in nur zusammen mit einer Erwähnung von hasOwnProperty() und anderen weniger offensichtlichen Randfällen der prototypischen Vererbung gelehrt werden sollte.

0 Stimmen

Interessanterweise funktioniert dies nicht für Getter-Eigenschaften, die mit Object.defineProperty definiert wurden, aber für direkte Getter. Siehe mein jsfiddle .

29 Stimmen

Ich denke Die meisten die Leute sind überrascht, dass for(x in {}) überhaupt etwas aufzählt, da es wie eine einfache Iteration von Wörterbuchschlüsseln aussieht. Das ist sehr unerwartet und verdient definitiv eine besondere Warnung.

236voto

Ryan Grove Punkte 2899

Verwenden Sie eine for..in Schleife verwenden, um die Eigenschaften eines Objekts aufzuzählen, aber seien Sie vorsichtig. Die Aufzählung gibt nicht nur die Eigenschaften des aufgezählten Objekts zurück, sondern auch die der Prototypen aller übergeordneten Objekte.

var myObject = {foo: 'bar'};

for (var name in myObject) {
  alert(name);
}

// results in a single alert of 'foo'

Object.prototype.baz = 'quux';

for (var name in myObject) {
  alert(name);
}

// results in two alerts, one for 'foo' and one for 'baz'

Um zu vermeiden, dass geerbte Eigenschaften in Ihre Aufzählung aufgenommen werden, überprüfen Sie hasOwnProperty() :

for (var name in myObject) {
  if (myObject.hasOwnProperty(name)) {
    alert(name);
  }
}

Editar: Ich stimme nicht mit JasonBunting's Aussage überein, dass wir uns nicht um die Aufzählung von vererbten Eigenschaften kümmern müssen. Es es Die Gefahr beim Aufzählen von geerbten Eigenschaften, die Sie nicht erwarten, besteht darin, dass sie das Verhalten Ihres Codes verändern können.

Es spielt keine Rolle, ob dieses Problem auch in anderen Sprachen besteht; Tatsache ist, dass es existiert und JavaScript besonders anfällig ist, da Änderungen am Prototyp eines Objekts sich auf untergeordnete Objekte auswirken, selbst wenn die Änderung nach der Instanziierung erfolgt.

Aus diesem Grund bietet JavaScript hasOwnProperty() Deshalb sollten Sie es verwenden, um sicherzustellen, dass der Code von Dritten (oder jeder andere Code, der einen Prototyp verändern könnte) den Ihren nicht beschädigt. Abgesehen vom Hinzufügen einiger zusätzlicher Bytes an Code gibt es keinen Nachteil bei der Verwendung von hasOwnProperty() .

4 Stimmen

Die Anhänger von hasOwnProperty sind in der Regel diejenigen, die a) unter aggressiven gemeinsamen Bibliotheken gelitten haben [z.B.: Prototype.js um 2003], oder b) Grundlagen für heterogene Systeme gebaut haben (z.B.: Webportale). Alle anderen sollten hasOwnProperty einfach in ein Iterator-Muster verpacken und ein Bier trinken gehen.

31 Stimmen

Dieses Muster wird benötigt und verwendet, weil Javascript "Actor-Objekte" mit "Hash-Tabellen" verwechselt. wenn das Objekt ein Beschreibung von Verhaltensweisen und Merkmalen dann gelten die üblichen Regeln: Sie wollen die Eigenschaften des Objekts kennen, ohne sich darum zu kümmern, wie sie dorthin gekommen sind. Wenn Sie das Objekt hingegen als Key-Value-Speicher verwenden, sind Sie wahrscheinlich nur an den tatsächlichen Schlüsseln interessiert, die tatsächlich im Objekt gespeichert sind. Andere Eigenschaften sind zufällig und repräsentieren nicht den tatsächlichen Zustand des Objekts. Andere Sprachen lösen diese Unterscheidung mit unterschiedlichen Typen.

0 Stimmen

Für mein Verständnis als js-Neuling, wie funktioniert Object.prototype.baz = 'quux'; ändern Sie die myObject Objekt?

52voto

Carlos Ruana Punkte 1908

In modernen Browsern (ECMAScript 5) können Sie alle aufzählbaren Eigenschaften abrufen:

Object.keys(obj) (Überprüfen Sie den Link, um ein Snippet für die Abwärtskompatibilität mit älteren Browsern zu erhalten)

Oder um auch nicht aufzählbare Eigenschaften zu erhalten:

Object.getOwnPropertyNames(obj)

ECMAScript 5-Kompatibilitätstabelle prüfen

Zusätzliche Informationen: Was ist ein aufzählbares Attribut?

3 Stimmen

Object.getOwnPropertyNames(obj) ist das, was Sie wollen, wenn Sie mit einer Art von Fehlerobjekt (z. B. TypeError) zu tun haben, weil die Eigenschaften nicht aufzählbar sind.

0 Stimmen

@vossad01 Leider getOwnPropertyNames scheint nicht zu funktionieren mit ErrorEvent Objekte: Es werden nur isTrusted . Allerdings for( var pn in errEv ) console.log( pn ); } tut arbeiten. Das ist frustrierend und inkonsequent.

50voto

Fabian Jakobs Punkte 27936

Der Standardweg, der bereits mehrfach vorgeschlagen wurde, ist:

for (var name in myObject) {
  alert(name);
}

Internet Explorer 6, 7 und 8 haben jedoch einen Fehler im JavaScript-Interpreter, der dazu führt, dass einige Schlüssel nicht aufgezählt werden. Wenn Sie diesen Code ausführen:

var obj = { toString: 12};
for (var name in obj) {
  alert(name);
}

In allen Browsern außer dem IE wird "12" angezeigt. Der IE ignoriert diese Taste einfach. Die betroffenen Schlüsselwerte sind:

  • isPrototypeOf
  • hasOwnProperty
  • toLocaleString
  • toString
  • valueOf

Um im IE wirklich sicher zu sein, müssen Sie etwas wie:

for (var key in myObject) {
  alert(key);
}

var shadowedKeys = [
  "isPrototypeOf",
  "hasOwnProperty",
  "toLocaleString",
  "toString",
  "valueOf"
];
for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) {
  if map.hasOwnProperty(a[i])) {
    alert(a[i]);
  }
}

Die gute Nachricht ist, dass EcmaScript 5 die Object.keys(myObject) Funktion, die die Schlüssel eines Objekts als Array zurückgibt, und einige Browser (z. B. Safari 4) implementieren sie bereits.

27voto

cyberhobo Punkte 606

Ich denke, ein Beispiel für einen Fall, der mich überrascht hat, ist relevant:

var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
  document.writeln( propertyName + " : " + myObject[propertyName] );
}

Doch zu meiner Überraschung lautet die Ausgabe

name : Cody
status : Surprised
forEach : function (obj, callback) {
    for (prop in obj) {
        if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
            callback(prop);
        }
    }
}

Warum? Ein anderes Skript auf der Seite hat den Prototyp Object erweitert:

Object.prototype.forEach = function (obj, callback) {
  for ( prop in obj ) {
    if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
      callback( prop );
    }
  }
};

0 Stimmen

Interessant, ich nehme an, das bedeutet, dass es möglich ist, den Rückruf NICHT aufrufen, wenn die forEach-Funktion neu zu definieren, die Aufzählung der Eigenschaften brechen machen könnte.

0 Stimmen

Ja, ich will damit sagen, dass ein anderes Skript dem Objektprototyp alles Mögliche hätte hinzufügen können. Solche Änderungen können vorhanden sein oder auch nicht, und hinzugefügte Methoden können alles Mögliche tun. Ich behaupte nicht, dass dieses Beispiel von forEach gut ist - es ist nur etwas, was ein Skript tun könnte, das die Ergebnisse von for in für andere Skripte verändern würde.

0 Stimmen

Angesichts der modernen Trends in der JavaScript-Entwicklung scheint mir die Änderung des Prototyps eines der Basistypen eine schlechte Entscheidung zu sein; es gibt andere Wege, die meisten der Katzen zu häuten, die die Leute dazu bringen, es überhaupt zu tun.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X