Start · Sprachen · JavaScript · Referenz · handler.getPrototypeOf()

handler.getPrototypeOf()

Methode

Falle (Trap) eines Proxy-Handlers, die die interne Methode <code>[[GetPrototypeOf]]</code> abfängt, z. B. bei <code>Object.getPrototypeOf()</code> oder <code>instanceof</code>.

seit JavaScript ES2015 Kategorie: method-property

Signatur

new Proxy(target, { getPrototypeOf(target) { … } })

Beschreibung

Die Methode handler.getPrototypeOf() ist eine Falle (Trap) im Handler-Objekt eines Proxy. Sie wird immer dann aufgerufen, wenn die JavaScript-Engine den Prototyp des Proxys ermitteln will, also bei der internen Operation [[GetPrototypeOf]]. Mit ihr lässt sich steuern, welchen Prototyp ein Objekt nach außen vorgibt zu haben.

Die Falle wird unter anderem ausgelöst durch:

  • Object.getPrototypeOf(proxy) und Reflect.getPrototypeOf(proxy)
  • Object.prototype.isPrototypeOf(), z. B. Array.prototype.isPrototypeOf(proxy)
  • den Operator instanceof (bei der Prototypkette des linken Operanden)
  • den Accessor proxy.__proto__

Typische Einsatzzwecke sind das Maskieren oder Verschleiern des echten Typs, das Protokollieren von Prototyp-Abfragen, Sandboxing sowie das Nachbilden von Vererbung bei Wrapper-Objekten. Wird die Falle nicht definiert, leitet der Proxy die Operation unverändert an das Zielobjekt weiter – dasselbe erreicht man explizit mit Reflect.getPrototypeOf(target).

Die Rückgabe muss ein Objekt oder null sein. Außerdem gilt eine Invariante: Ist das Zielobjekt nicht erweiterbar (Object.isExtensible(target) === false), muss die Falle genau den echten Prototyp des Ziels zurückgeben. Sonst wirft die Engine einen TypeError.

Parameter

Name Typ Default Beschreibung
$target Pflicht object Das Zielobjekt, das der Proxy umhüllt. Der Handler-Kontext this ist an das Handler-Objekt gebunden.

Rückgabewert

Typ
object | null
Beschreibung
Das Objekt, das als Prototyp des Proxys gemeldet werden soll, oder null. Andere Werte (z. B. Zahlen, Strings, undefined) führen zu einem TypeError.

Beispiele

Prototyp-Abfragen protokollieren und durchreichen

const user = { name: 'Anna' };

const proxy = new Proxy(user, {
  getPrototypeOf(target) {
    console.log('Prototyp wird abgefragt');
    return Reflect.getPrototypeOf(target);
  }
});

console.log(Object.getPrototypeOf(proxy) === Object.prototype);
Prototyp wird abgefragt true

Einen anderen Typ vortäuschen (instanceof)

class Admin {}

const plain = { role: 'admin' };

const fakeAdmin = new Proxy(plain, {
  getPrototypeOf() {
    return Admin.prototype;
  }
});

console.log(fakeAdmin instanceof Admin);
console.log(Admin.prototype.isPrototypeOf(fakeAdmin));
console.log(Object.getPrototypeOf(plain) === Object.prototype);
true true true

Prototyp verbergen (Sandboxing)

const secret = new Map([['key', 42]]);

const hidden = new Proxy(secret, {
  getPrototypeOf() {
    return null; // Prototypkette nach außen verschleiern
  }
});

console.log(Object.getPrototypeOf(hidden));
console.log(hidden instanceof Map);
null false

Invariante verletzt: nicht erweiterbares Ziel

const target = Object.preventExtensions({});

const proxy = new Proxy(target, {
  getPrototypeOf() {
    return Array.prototype; // weicht vom echten Prototyp ab
  }
});

try {
  Object.getPrototypeOf(proxy);
} catch (err) {
  console.log(err instanceof TypeError);
}
true

// Wichtig · Fallstricke

  • Rückgabetyp: Nur ein Objekt oder null ist erlaubt, alles andere wirft einen TypeError.
  • Invariante: Ist das Ziel nicht erweiterbar (Object.preventExtensions, Object.seal, Object.freeze), muss die Falle Object.getPrototypeOf(target) zurückgeben.
  • Nur Schein: Die Falle ändert nur, was Abfragen melden. Das Nachschlagen von Eigenschaften (proxy.foo) läuft weiterhin über die get-Falle bzw. die echte Prototypkette des Ziels. Wer die Vererbung wirklich umbiegen will, muss zusätzlich get und has abfangen.
  • instanceof: Hat die Klasse eine eigene Symbol.hasInstance-Methode, wird diese statt der Prototypkette verwendet, und die Falle wird dann eventuell gar nicht aufgerufen.
  • Performance: Häufige Prototyp-Abfragen über Proxys sind deutlich langsamer als bei normalen Objekten. In heißen Codepfaden sollte man das vermeiden.
  • Kompatibilität: Wird von allen modernen Browsern und von Node.js (ab 6) unterstützt. Im Internet Explorer gibt es das nicht, und Proxys lassen sich nicht per Polyfill nachrüsten.