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

handler.get()

Methode

Die Falle <code>handler.get()</code> fängt Lesezugriffe auf Eigenschaften eines Proxys ab (interne Methode <code>[[Get]]</code>), z. B. <code>proxy.foo</code> oder <code>proxy["foo"]</code>.

seit JavaScript ES2015 Kategorie: method-property

Signatur

new Proxy(target, { get(target, property, receiver) { … } })

Beschreibung

handler.get() ist die wohl am häufigsten genutzte Falle eines Proxy. Sie wird jedes Mal aufgerufen, wenn eine Eigenschaft des Proxys gelesen wird. Dazu zählen Punkt- und Klammerschreibweise (proxy.x, proxy[key]), Destrukturierung (const { x } = proxy), Reflect.get() und auch Lesezugriffe über die Prototypkette, wenn der Proxy als Prototyp eines anderen Objekts dient.

Typische Anwendungsfälle sind Standardwerte für fehlende Eigenschaften, Protokollierung und Debugging, Validierung (z. B. einen Fehler bei unbekannten Schlüsseln werfen), negative Array-Indizes, Lazy Loading sowie reaktive Systeme, die Abhängigkeiten beim Lesen erfassen (wie in Vue 3).

Der Rückgabewert der Falle ist das Ergebnis des Zugriffs. Um das Standardverhalten weiterzuleiten, solltest du Reflect.get(target, property, receiver) verwenden statt target[property], denn nur so werden Getter mit dem richtigen this (dem receiver) ausgeführt.

Die Falle muss bestimmte Invarianten einhalten: Ist eine Eigenschaft des Ziels nicht konfigurierbar und nicht beschreibbar, muss genau ihr Wert zurückgegeben werden. Ist sie eine nicht konfigurierbare Accessor-Eigenschaft ohne Getter, muss undefined zurückgegeben werden. Bei einem Verstoß wirft die Engine einen TypeError.

Parameter

Name Typ Default Beschreibung
$target Pflicht object Das Zielobjekt, das der Proxy umhüllt.
$property Pflicht string | symbol Name der gelesenen Eigenschaft. Zahlen-Indizes kommen als String an (z. B. "0"), Symbole bleiben Symbole.
$receiver Pflicht object Das Objekt, auf dem der Zugriff ursprünglich erfolgte – meist der Proxy selbst, bei Vererbung aber das erbende Objekt. Wird als this für Getter benötigt.

Rückgabewert

Typ
any
Beschreibung
Ein beliebiger Wert, der als Ergebnis des Eigenschaftszugriffs geliefert wird.

Beispiele

Standardwert für fehlende Eigenschaften

const config = { host: 'localhost' };

const withDefaults = new Proxy(config, {
  get(target, prop, receiver) {
    // Existiert die Eigenschaft, normal weiterleiten
    if (prop in target) {
      return Reflect.get(target, prop, receiver);
    }
    return `(nicht gesetzt: ${String(prop)})`;
  }
});

console.log(withDefaults.host);
console.log(withDefaults.port);
localhost (nicht gesetzt: port)

Negative Array-Indizes wie in Python

const negativeArray = (arr) => new Proxy(arr, {
  get(target, prop, receiver) {
    // Indizes kommen als String an
    if (typeof prop === 'string' && /^-\d+$/.test(prop)) {
      prop = String(target.length + Number(prop));
    }
    return Reflect.get(target, prop, receiver);
  }
});

const farben = negativeArray(['rot', 'grün', 'blau']);
console.log(farben[-1]);
console.log(farben[-3]);
console.log(farben.length);
blau rot 3

Strenges Objekt: Tippfehler sofort erkennen

const strict = (obj) => new Proxy(obj, {
  get(target, prop, receiver) {
    // Symbole (z. B. Symbol.toPrimitive) durchlassen
    if (typeof prop === 'symbol' || prop in target) {
      return Reflect.get(target, prop, receiver);
    }
    throw new ReferenceError(`Unbekannte Eigenschaft: "${prop}"`);
  }
});

const user = strict({ name: 'Anna', role: 'admin' });
console.log(user.name);

try {
  console.log(user.rolle);
} catch (err) {
  console.error(err.message);
}
Anna Unbekannte Eigenschaft: "rolle"

Warum receiver wichtig ist: Getter mit this

const person = {
  _name: 'Ben',
  get name() { return this._name.toUpperCase(); }
};

const proxy = new Proxy(person, {
  get(target, prop, receiver) {
    console.log(`Lese ${String(prop)}`);
    return Reflect.get(target, prop, receiver);
  }
});

// Durch receiver läuft auch this._name über den Proxy
console.log(proxy.name);
Lese name Lese _name BEN

// Wichtig · Fallstricke

  • Invarianten: Für nicht konfigurierbare, nicht beschreibbare Dateneigenschaften des Ziels (z. B. nach Object.freeze()) muss der echte Wert zurückgegeben werden, sonst folgt ein TypeError.
  • Reflect.get statt target[prop]: Mit target[prop] laufen Getter mit this === target, dann greifen verschachtelte Zugriffe nicht mehr auf die Falle zurück. Das führt z. B. bei Vererbung oder reaktiven Systemen zu schwer auffindbaren Fehlern.
  • Eigenschaftsnamen sind Strings oder Symbole: proxy[0] kommt als "0" an. Außerdem fragen Engines, console.log, Template-Strings und await interne Symbole bzw. Schlüssel ab (Symbol.toPrimitive, Symbol.iterator, then). Eine Falle, die bei unbekannten Schlüsseln einen Fehler wirft, kann deshalb unerwartet auslösen. Symbole und then solltest du gezielt durchlassen.
  • Interne Slots: Proxys um Map, Set, Date oder DOM-Objekte scheitern bei Methodenaufrufen (TypeError: incompatible receiver), weil this der Proxy ist. Abhilfe: Funktionen in der Falle mit value.bind(target) zurückgeben.
  • Leistung: Jeder Lesezugriff ruft eine Funktion auf. In heißen Schleifen ist das deutlich langsamer als ein direkter Zugriff.
  • Kompatibilität: Wird von allen modernen Browsern und Node.js 6+ unterstützt. Ein Polyfill ist nicht möglich, Internet Explorer wird nicht unterstützt.