Signatur
Beschreibung
Die Eigenschaft constructor liegt normalerweise nicht direkt auf der Instanz, sondern auf dem Prototyp ihres Konstruktors. Jede gewöhnliche Funktion (und jede Klasse) bekommt beim Anlegen ein prototype-Objekt, dessen constructor auf die Funktion selbst zurückverweist. Instanzen erben diese Eigenschaft über die Prototypkette: new Foo().constructor === Foo.
Typische Einsatzzwecke sind: aus einer vorhandenen Instanz eine neue Instanz desselben Typs erzeugen (new obj.constructor()), den Klassennamen für Logs oder Debugging auslesen (obj.constructor.name) und in generischem Code (Klonen, Serialisieren) den Typ eines Objekts bestimmen.
Wichtig: constructor ist eine ganz normale, beschreibbare und nicht aufzählbare Dateneigenschaft. Sie lässt sich überschreiben oder geht verloren, wenn man prototype komplett ersetzt. Für verlässliche Typprüfungen eignen sich daher instanceof, Array.isArray() oder Object.prototype.toString.call() besser.
Primitive Werte wie 1 oder "abc" werden beim Zugriff kurzzeitig in ihre Wrapper-Objekte umgewandelt, daher liefert (1).constructor die Funktion Number. Objekte ohne Prototyp (Object.create(null)) besitzen keine constructor-Eigenschaft.
Rückgabewert
undefined, wenn in der Prototypkette keine constructor-Eigenschaft existiert, z. B. bei Object.create(null).Beispiele
Konstruktor eingebauter Typen auslesen
console.log({}.constructor === Object);
console.log([].constructor === Array);
console.log((42).constructor === Number);
console.log('text'.constructor.name);
console.log(Object.create(null).constructor);
Neue Instanz desselben Typs erzeugen
class Vector {
constructor(x = 0, y = 0) { this.x = x; this.y = y; }
add(other) {
// Funktioniert auch für Unterklassen, weil this.constructor dynamisch ist
return new this.constructor(this.x + other.x, this.y + other.y);
}
}
class Vector2D extends Vector {}
const v = new Vector2D(1, 2).add(new Vector2D(3, 4));
console.log(v.constructor.name, v.x, v.y);
console.log(v instanceof Vector2D);
Verlorener constructor nach Ersetzen von prototype
function Person(name) { this.name = name; }
// Prototyp komplett ersetzt – constructor zeigt jetzt auf Object!
Person.prototype = {
greet() { return `Hallo, ${this.name}`; }
};
const p = new Person('Anna');
console.log(p.constructor === Person); // false
console.log(p.constructor === Object); // true
// Korrekt wiederherstellen (nicht aufzählbar wie das Original)
Object.defineProperty(Person.prototype, 'constructor', {
value: Person,
writable: true,
configurable: true,
enumerable: false
});
console.log(new Person('Ben').constructor === Person);
Typname für Logging ermitteln
const typeName = (value) =>
value == null ? String(value) : value.constructor?.name ?? 'Object (ohne Prototyp)';
console.log(typeName(new Map()));
console.log(typeName(new Date()));
console.log(typeName(null));
console.log(typeName(Object.create(null)));
// Wichtig · Fallstricke
- Nicht fälschungssicher:
constructorist beschreibbar –obj.constructor = Arrayist erlaubt. Für Typprüfungen besserinstanceof,Array.isArray()oderObject.prototype.toString.call(obj)verwenden. - Vererbung mit Funktionen: Nach
Child.prototype = Object.create(Parent.prototype)zeigtconstructoraufParent. Man muss ihn manuell (am besten perObject.defineProperty, nicht aufzählbar) aufChildzurücksetzen. Beiclass … extendspassiert das automatisch. - Realms: Objekte aus einem anderen
iframeoder Worker haben einen anderenArray- bzw.Object-Konstruktor,arr.constructor === Arrayist dannfalse. null/undefined: Zugriff aufconstructorwirft einenTypeError; optionale Verkettung (value?.constructor) hilft.- Minifizierung:
constructor.namekann durch Minifizierer verändert werden – nicht für Programmlogik verwenden. - Eingebaute Methoden wie
Array.prototype.mapermitteln überconstructor[Symbol.species]den Typ des Ergebnisses; ein manipulierterconstructorkann dieses Verhalten beeinflussen.