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

handler.construct()

Methode

Trap für die interne Methode <code>[[Construct]]</code>: fängt <code>new</code>-Aufrufe auf einem Proxy ab und muss ein Objekt zurückgeben.

seit JavaScript ES2015 Kategorie: method-property

Signatur

new Proxy(target, { construct(target, argumentsList, newTarget) { … } })

Beschreibung

Die Methode handler.construct() ist ein Trap eines Proxy-Handlers. Sie wird aufgerufen, wenn der Proxy mit dem new-Operator instanziiert wird (new proxy(...args)), oder über Reflect.construct(). Ebenso löst ein super(...)-Aufruf in einer abgeleiteten Klasse, deren Elternklasse ein Proxy ist, den Trap aus.

Typische Einsatzgebiete sind Logging und Profiling von Instanziierungen, Validierung von Konstruktor-Argumenten, Singleton- oder Pool-Muster (immer dieselbe Instanz zurückgeben), Dependency Injection sowie das Einschleusen von Standardwerten, ohne die Originalklasse zu verändern.

Wichtig: Damit der Trap überhaupt greift, muss das target selbst konstruierbar sein, also eine interne Methode [[Construct]] besitzen (normale Funktionen, Klassen). Ein Proxy um ein einfaches Objekt oder eine Pfeilfunktion kann nicht mit new aufgerufen werden – es entsteht ein TypeError, noch bevor der Trap läuft.

Um das Standardverhalten innerhalb des Traps auszuführen, nutzt man Reflect.construct(target, argumentsList, newTarget). Durch die Weitergabe von newTarget bleibt die Vererbung (Prototyp der Instanz) auch bei Unterklassen korrekt.

Parameter

Name Typ Default Beschreibung
$target Pflicht Function Das ursprüngliche Zielobjekt des Proxys. Muss konstruierbar sein (Funktion oder Klasse).
$argumentsList Pflicht Array Array mit den Argumenten, die an new übergeben wurden.
$newTarget Pflicht Function Der Konstruktor, der ursprünglich mit new aufgerufen wurde – meist der Proxy selbst, bei Unterklassen die abgeleitete Klasse. Entspricht new.target.

Rückgabewert

Typ
object
Beschreibung
Muss ein Objekt (auch Funktion oder Array) zurückgeben. Wird ein primitiver Wert (z. B. undefined, Zahl, String) zurückgegeben, wirft die Engine einen TypeError.

Beispiele

Instanziierungen protokollieren

class User {
  constructor(name) {
    this.name = name;
  }
}

const LoggedUser = new Proxy(User, {
  construct(target, args, newTarget) {
    console.log(`new ${target.name}(${args.join(', ')})`);
    return Reflect.construct(target, args, newTarget);
  }
});

const u = new LoggedUser('Anna');
console.log(u instanceof User, u.name);
new User(Anna) true Anna

Konstruktor-Argumente validieren

class Temperature {
  constructor(celsius) {
    this.celsius = celsius;
  }
}

const SafeTemperature = new Proxy(Temperature, {
  construct(target, [celsius], newTarget) {
    if (typeof celsius !== 'number' || celsius < -273.15) {
      throw new RangeError(`Ungültige Temperatur: ${celsius}`);
    }
    return Reflect.construct(target, [celsius], newTarget);
  }
});

console.log(new SafeTemperature(21).celsius);
try {
  new SafeTemperature(-300);
} catch (err) {
  console.log(err.message);
}
21 Ungültige Temperatur: -300

Singleton erzwingen

class Config {
  constructor() {
    this.createdAt = Date.now();
  }
}

const makeSingleton = (Cls) => {
  let instance = null;
  return new Proxy(Cls, {
    construct(target, args, newTarget) {
      instance ??= Reflect.construct(target, args, newTarget);
      return instance;
    }
  });
};

const AppConfig = makeSingleton(Config);
const a = new AppConfig();
const b = new AppConfig();
console.log(a === b);
true

Fehler: Trap gibt keinen Objektwert zurück

const P = new Proxy(function () {}, {
  construct() {
    return 42; // primitiver Wert – nicht erlaubt
  }
});

try {
  new P();
} catch (err) {
  console.log(err.constructor.name);
}
TypeError

// Wichtig · Fallstricke

  • Rückgabewert muss ein Objekt sein: Anders als bei normalen Konstruktoren wird ein primitiver Rückgabewert nicht ignoriert, sondern führt zu einem TypeError. Auch ein fehlendes return (also undefined) löst den Fehler aus.
  • Ziel muss konstruierbar sein: new Proxy({}, { construct() { return {}; } }) lässt sich nicht mit new aufrufen. Pfeilfunktionen und Methoden-Kurzschreibweisen haben ebenfalls kein [[Construct]].
  • newTarget weitergeben: Wer new target(...args) statt Reflect.construct(target, args, newTarget) verwendet, verliert bei Unterklassen den richtigen Prototyp – instanceof der Unterklasse liefert dann false.
  • this im Trap ist das Handler-Objekt, nicht die neue Instanz.
  • Normale Funktionsaufrufe ohne new werden nicht von construct, sondern vom Trap apply abgefangen.
  • Proxy-Traps kosten Leistung; bei sehr häufigen Instanziierungen in heißen Codepfaden sparsam einsetzen. Proxies lassen sich nicht polyfillen – unterstützt von allen modernen Browsern und Node.js ab Version 6.