Object.hasOwn vs. hasOwnProperty: Sichere Property-Prüfung ohne Fallstricke
AI generated
JS
() =>
JavaScript · ES2022 · Objekte · Sicherheit
Object.hasOwn vs. hasOwnProperty
Sichere Property-Prüfung ohne Fallstricke

obj.hasOwnProperty(key) sieht harmlos aus, bricht aber bei null-Prototyp-Objekten und bei überschriebenen Prototyp-Methoden. Object.hasOwn(obj, key) ist die statische, robuste Alternative, die genau diese Fallstricke umschifft und in modernem Code die Standardwahl für Property-Prüfungen sein sollte.

13 Min. Lesezeit Object.hasOwn · Prototyp-Ketten · Object.create(null) · Proxy Node 16.9+ · Chrome 93+ · ES2022

1. Warum eine neue Methode für etwas so Simples?

Auf den ersten Blick wirkt Object.hasOwn wie eine überflüssige Ergänzung: obj.hasOwnProperty(key) gibt es schon seit den Anfängen von JavaScript und macht scheinbar genau dasselbe. Der Unterschied liegt aber genau in dem Wort "scheinbar". hasOwnProperty ist eine Methode, die vom Prototyp geerbt wird, und genau diese Vererbung ist die Quelle mehrerer subtiler Bugs, die in echtem Code immer wieder auftreten.

Object.hasOwn löst das Problem, indem es die Prüfung als statische Funktion implementiert, die unabhängig vom geprüften Objekt selbst funktioniert. Statt eine Methode auf dem Objekt aufzurufen, das theoretisch manipuliert oder gar nicht vorhanden sein kann, übergibt man das Objekt als Argument an eine Funktion, die auf Object selbst lebt. Diese scheinbar kleine Verschiebung der Verantwortung ist der eigentliche Kern, warum Object.hasOwn in modernem JavaScript-Code die sicherere Wahl ist.

2. Object.hasOwn: Syntax und Rückgabewert

Die Syntax von Object.hasOwn ist bewusst einfach gehalten: Object.hasOwn(obj, prop) nimmt das zu prüfende Objekt als erstes und den Property-Namen als zweites Argument und gibt einen Boolean zurück, der genau angibt, ob das Objekt eine eigene, direkte Property mit diesem Namen besitzt. Vererbte Properties vom Prototyp werden dabei bewusst ignoriert, exakt wie bei der klassischen hasOwnProperty-Methode.

Der entscheidende Vorteil zeigt sich erst bei der Aufruf-Syntax: Object.hasOwn wird niemals auf dem zu prüfenden Objekt selbst aufgerufen, sondern immer auf Object. Das bedeutet, es ist völlig irrelevant, welchen Prototyp das übergebene Objekt hat, ob es eigene Methoden überschreibt oder ob es überhaupt eine funktionierende Prototyp-Kette besitzt. Diese Entkopplung ist der eigentliche technische Fortschritt gegenüber der alten Methode.


const config = { debug: true, retries: 3 };

// Object.hasOwn: static call, independent of the object's prototype
console.log(Object.hasOwn(config, "debug"));   // true
console.log(Object.hasOwn(config, "toString")); // false — inherited, not own

// Old approach: method call on the object itself
console.log(config.hasOwnProperty("debug"));    // true, works fine here

3. Das null-Prototyp-Problem: wenn hasOwnProperty verschwindet

Der offensichtlichste Fehlerfall für hasOwnProperty tritt bei Objekten auf, die mit Object.create(null) erzeugt wurden. Solche Objekte besitzen bewusst keinen Prototyp, was in sicherheitsrelevantem Code häufig gewünscht ist, um Prototype Pollution von vornherein auszuschließen. Das Problem: ohne Prototyp gibt es auch keine geerbte hasOwnProperty-Methode, und der Aufruf obj.hasOwnProperty(key) wirft eine TypeError-Exception, weil die Methode schlicht nicht existiert.

Object.hasOwn hat mit diesem Fall überhaupt kein Problem, weil die Prüfung niemals auf dem Objekt selbst aufgerufen wird. Ein null-Prototyp-Objekt lässt sich mit Object.hasOwn genauso sicher prüfen wie ein gewöhnliches Objekt-Literal. Wer defensiv programmiert und häufig Object.create(null) für Konfigurationsobjekte oder Lookup-Tabellen einsetzt, um Kollisionen mit Prototyp-Properties zu vermeiden, profitiert hier direkt und ohne zusätzlichen Aufwand.


// Object.create(null) has no prototype at all
const dictionary = Object.create(null);
dictionary.hello = "welt";

// This throws: TypeError, hasOwnProperty does not exist on this object
try {
  dictionary.hasOwnProperty("hello");
} catch (err) {
  console.error(err.message); // dictionary.hasOwnProperty is not a function
}

// Object.hasOwn works regardless of the object's prototype chain
console.log(Object.hasOwn(dictionary, "hello")); // true
console.log(Object.hasOwn(dictionary, "world")); // false

4. Überschriebene hasOwnProperty-Methoden als Angriffsfläche

Ein zweiter, subtilerer Fehlerfall entsteht, wenn ein Objekt selbst eine Property namens hasOwnProperty definiert, die nicht die geerbte Methode ist. Das passiert häufiger als man denkt, etwa bei Objekten, die dynamisch aus unsicheren Datenquellen wie Formulareingaben oder JSON-Payloads zusammengesetzt werden. Ist in diesen Daten ein Schlüssel hasOwnProperty enthalten, überschreibt er die geerbte Methode, und der nächste Aufruf von obj.hasOwnProperty(key) ruft plötzlich nicht mehr die erwartete Prüfung auf, sondern den überschriebenen Wert.

Object.hasOwn ist gegen diese Art von Manipulation vollständig immun, weil die Prüfung nie auf dem potenziell kompromittierten Objekt aufgerufen wird. In sicherheitskritischem Code, der mit Nutzereingaben oder externen APIs arbeitet, ist das ein reales Härtungsmerkmal und kein theoretisches Detail. Wer Objekte aus unsicheren Quellen prüft, sollte konsequent Object.hasOwn statt der Methode auf dem Objekt verwenden.

5. Object.hasOwn mit Proxy-Objekten

Proxy-Objekte fügen eine weitere Ebene der Komplexität hinzu. Ein Proxy kann den has-Trap und den getOwnPropertyDescriptor-Trap implementieren, um das Verhalten von Property-Prüfungen komplett anzupassen. Object.hasOwn respektiert diese Traps korrekt, weil es intern auf [[GetOwnProperty]] basiert, denselben internen Mechanismus, den auch Object.getOwnPropertyDescriptor nutzt. Ein Proxy, der bestimmte Properties gezielt verstecken oder simulieren will, funktioniert also mit Object.hasOwn genau wie erwartet.

Das ist relevant für Frameworks und Bibliotheken, die reaktive Objekte über Proxys implementieren, etwa Zustandsverwaltung in modernen Frontend-Architekturen. Prüft eine solche Bibliothek intern mit Object.hasOwn, statt sich auf die Objektmethode zu verlassen, bleibt das Verhalten auch dann korrekt, wenn Anwender eigene Proxy-Wrapper um die reaktiven Objekte legen. Diese Konsistenz war mit der alten Methode nicht garantiert.


const hidden = new Proxy({ secret: 42, visible: 1 }, {
  getOwnPropertyDescriptor(target, prop) {
    if (prop === "secret") return undefined; // hide this property
    return Object.getOwnPropertyDescriptor(target, prop);
  }
});

console.log(Object.hasOwn(hidden, "secret"));  // false — trap respected
console.log(Object.hasOwn(hidden, "visible")); // true

6. Praxisfall: Sichere Objektiteration mit for...in

Die klassische Kombination for...in mit hasOwnProperty-Filterung ist ein jahrealtes Pattern, um bei der Iteration über ein Objekt nur die eigenen Properties zu berücksichtigen und geerbte Prototyp-Properties zu ignorieren. In Code, der mit generischen Objekten unbekannter Herkunft arbeitet, sollte diese Filterung immer mit Object.hasOwn statt der Methode auf dem Objekt erfolgen, um gegen die zuvor beschriebenen Fallstricke abgesichert zu sein.

In neuerem Code ist Object.entries oder Object.keys häufig die bessere Wahl, weil beide von sich aus nur eigene, aufzählbare Properties liefern und keine Filterung benötigen. Trifft man aber auf for...in-Schleifen in Bestandscode, etwa beim Durcharbeiten älterer Codebasen, ist der Austausch der Filterbedingung gegen Object.hasOwn eine risikoarme, punktuelle Verbesserung.


const merged = Object.assign(Object.create({ inherited: "from prototype" }), {
  own1: "a",
  own2: "b"
});

// Safe iteration: only own properties, robust against overridden methods
for (const key in merged) {
  if (Object.hasOwn(merged, key)) {
    console.log(key, merged[key]); // own1 a / own2 b — "inherited" is skipped
  }
}

7. Vom JSON kommende Objekte prüfen

Objekte, die aus JSON.parse stammen, haben immer den normalen Object.prototype und funktionieren mit beiden Methoden in den meisten Fällen problemlos. Die Ausnahme entsteht, sobald das JSON selbst Schlüssel wie hasOwnProperty, constructor oder __proto__ enthält, etwa bei Nutzereingaben, die in ein JSON-Objekt serialisiert wurden. In diesem Fall überschreibt der geparste Wert die geerbte Methode auf demselben Weg wie im vorherigen Abschnitt beschrieben.

Wer Konfigurationsdateien, Webhook-Payloads oder Formulardaten als JSON verarbeitet, sollte grundsätzlich davon ausgehen, dass beliebige Schlüsselnamen vorkommen können. Object.hasOwn macht die Property-Prüfung in diesen Fällen unabhängig vom Inhalt der Daten und schließt eine ganze Klasse von Fehlern aus, die sonst erst in der Produktion auffallen würden, wenn genau der "falsche" Schlüsselname im JSON auftaucht.

8. Migration im Bestandscode: wann sich der Umstieg lohnt

Ein pauschaler Ersatz jeder hasOwnProperty-Verwendung durch Object.hasOwn ist selten notwendig, aber an bestimmten Stellen im Code hat der Umstieg klaren Mehrwert. Besonders relevant ist er bei Funktionen, die generische Objekte aus externen Quellen entgegennehmen, bei Utility-Funktionen in gemeinsam genutzten Bibliotheken und bei jedem Code, der mit Object.create(null) erzeugten Objekten arbeitet.

Bei internem Code, der ausschließlich mit selbst kontrollierten, einfachen Objekt-Literalen arbeitet, bringt der Umstieg wenig praktischen Nutzen, schadet aber auch nicht. Ein guter Kompromiss ist, Object.hasOwn als neuen Standard für alle neu geschriebenen Property-Prüfungen festzulegen, ohne bestehenden, funktionierenden Code aus reiner Konsequenz umzuschreiben. Linter-Regeln wie eslint-plugin-es-x können den Umstieg für neue Codeteile automatisch erzwingen.

9. Object.hasOwn im direkten Vergleich

Die folgende Tabelle stellt die wichtigsten Unterschiede zwischen der klassischen Methode und der neuen statischen Funktion gegenüber und zeigt, in welchen Situationen der Unterschied tatsächlich praktisch relevant wird.

Situation obj.hasOwnProperty(key) Object.hasOwn(obj, key) Ergebnis
Object.create(null) TypeError true / false Object.hasOwn funktioniert immer
Eigenes hasOwnProperty im Objekt Falsches Ergebnis Korrektes Ergebnis Object.hasOwn ist immun
Proxy mit eigenen Traps Abhängig vom Trap-Setup Respektiert Traps korrekt Beide möglich, hasOwn konsistenter
Gewöhnliches Objekt-Literal Funktioniert Funktioniert Kein praktischer Unterschied
Lesbarkeit im Code Methodenaufruf, vertraut Statischer Aufruf, expliziter Geschmacksfrage, leichter Vorteil hasOwn

In der Praxis zeigt sich: bei einfachen, selbst kontrollierten Objekten ist der Unterschied kosmetisch, bei Objekten unbekannter Herkunft wird Object.hasOwn zur echten Absicherung gegen Laufzeitfehler und Manipulation.

Mironsoft

Robuster JavaScript-Code und Absicherung gegen Laufzeitfehler

Code, der auch mit unsicheren Daten stabil bleibt?

Wir prüfen bestehenden JavaScript-Code auf fragile Property-Zugriffe, ersetzen veraltete Muster durch robuste Alternativen wie Object.hasOwn und härten eure Anwendungen gegen Prototype Pollution und manipulierte Objekte.

Security-Review

Objekt-Zugriffe und Prototyp-Ketten auf Manipulationsrisiken prüfen

Code-Modernisierung

Veraltete Property-Prüfungen durch moderne ES2022-Patterns ersetzen

Lint-Regeln

Automatisierte ESLint-Regeln für konsistente Property-Zugriffe einrichten

10. Zusammenfassung

Object.hasOwn löst ein Problem, das viele Entwickler jahrelang unterschätzt haben: die geerbte Methode hasOwnProperty kann durch null-Prototypen fehlen oder durch eigene Objekt-Properties überschrieben werden, und beide Fälle führen zu Laufzeitfehlern oder falschen Prüfergebnissen. Als statische Funktion auf Object ist Object.hasOwn gegen beide Fallstricke immun, weil die Prüfung nie auf dem potenziell kompromittierten Objekt selbst stattfindet.

Für neuen Code ist Object.hasOwn die klare Empfehlung, besonders bei Funktionen, die generische Objekte aus externen Quellen wie JSON-Payloads, Formulardaten oder Konfigurationsdateien entgegennehmen. Bei Objekten mit Object.create(null) oder Proxy-Wrappern ist der Umstieg nicht nur eine Stilfrage, sondern verhindert konkrete Bugs, die sonst erst in der Produktion sichtbar werden.

Object.hasOwn — Das Wichtigste auf einen Blick

Grundprinzip

Statische Funktion Object.hasOwn(obj, key) statt Methodenaufruf auf dem Objekt selbst, unabhängig vom Prototyp.

Null-Prototyp-Objekte

Funktioniert korrekt bei Object.create(null), während hasOwnProperty dort eine TypeError-Exception wirft.

Manipulationssicherheit

Immun gegen eigene hasOwnProperty-Properties im geprüften Objekt, relevant bei unsicheren Datenquellen.

Praxis-Empfehlung

Als Standard für neuen Code festlegen, besonders bei generischen Objekten und JSON-Payloads.

11. FAQ: Object.hasOwn vs. hasOwnProperty

1Hauptunterschied zwischen beiden Methoden?
Object.hasOwn ist statisch und nimmt das Objekt als Argument, hasOwnProperty wird auf dem Objekt selbst aufgerufen und hängt von dessen Prototyp ab.
2Warum scheitert hasOwnProperty bei Object.create(null)?
Ohne Prototyp fehlt die geerbte Methode komplett, der Aufruf wirft eine TypeError-Exception.
3Kann hasOwnProperty überschrieben werden?
Ja, ein eigener Schlüssel namens hasOwnProperty im Objekt überschreibt die geerbte Methode vollständig.
4Funktioniert es mit Proxy-Objekten?
Ja, Object.hasOwn respektiert korrekt implementierte Proxy-Traps wie getOwnPropertyDescriptor.
5Sollte ich allen Code umstellen?
Nicht pauschal, bei generischen Objekten aus externen Quellen aber klar empfehlenswert.
6Ist Object.hasOwn langsamer?
Nein, der Performance-Unterschied ist vernachlässigbar, beide nutzen denselben internen Mechanismus.
7Ab welcher Version verfügbar?
Node.js 16.9, Chrome 93, Firefox 92, Safari 15.4. Für ältere Umgebungen existieren Polyfills.
8Wie prüfe ich JSON-Daten am sichersten?
Immer Object.hasOwn, weil JSON-Schlüssel beliebige Namen tragen können, auch hasOwnProperty selbst.
9Ersetzt es den in-Operator?
Nein, in prüft auch vererbte Properties, Object.hasOwn nur eigene direkte Properties.
10In for...in-Schleifen nutzbar?
Ja, ein häufiger und robusterer Anwendungsfall als die klassische hasOwnProperty-Filterung.