Start · Sprachen · JavaScript · Referenz · Function: prototype

Function: prototype

Eigenschaft

Das Objekt in <code>funktion.prototype</code> wird zum Prototyp aller Instanzen, die mit <code>new funktion()</code> erzeugt werden.

seit JavaScript ES1 (Baseline: alle Browser) Kategorie: method-property

Signatur

Function.prototype.prototype (funktion.prototype)

Beschreibung

Jede „normale“ Funktion (Funktionsdeklaration, Funktionsausdruck, class) hat eine eigene Daten-Eigenschaft prototype. Ruft man die Funktion mit new auf, erzeugt die Engine ein neues Objekt, dessen internes [[Prototype]] auf funktion.prototype zeigt. Methoden und gemeinsame Eigenschaften, die dort liegen, stehen so allen Instanzen über die Prototypenkette zur Verfügung, ohne pro Instanz kopiert zu werden.

Standardmäßig ist prototype ein einfaches Objekt mit genau einer Eigenschaft: constructor, die zurück auf die Funktion verweist. Die Eigenschaft ist beschreibbar, nicht aufzählbar und nicht konfigurierbar. Bei Klassen ist prototype dagegen nicht beschreibbar.

Wichtig ist der Unterschied zu Object.getPrototypeOf(obj) bzw. obj.__proto__: funktion.prototype ist nicht der Prototyp der Funktion selbst (der ist Function.prototype), sondern die Vorlage für ihre Instanzen. Diese Eigenschaft wird auch von instanceof ausgewertet.

Pfeilfunktionen, Methoden-Kurzschreibweisen, async-Funktionen und die meisten eingebauten Funktionen (z. B. Math.max) haben keine prototype-Eigenschaft und können nicht mit new aufgerufen werden. Generatorfunktionen haben eine prototype-Eigenschaft (Prototyp der erzeugten Generator-Objekte), lassen sich aber trotzdem nicht als Konstruktor verwenden.

Rückgabewert

Typ
Object | undefined
Beschreibung
Das Prototyp-Objekt für Instanzen, die mit new erzeugt werden; standardmäßig { constructor: funktion }. Bei Funktionen ohne Konstruktor-Fähigkeit (Pfeilfunktionen, Methoden) undefined.

Beispiele

Gemeinsame Methoden für Konstruktor-Instanzen

function Benutzer(name) {
  this.name = name;
}

// Methode einmal auf dem Prototyp ablegen statt pro Instanz
Benutzer.prototype.begruessen = function () {
  return `Hallo, ${this.name}!`;
};

const anna = new Benutzer('Anna');
const ben = new Benutzer('Ben');

console.log(anna.begruessen());
console.log(anna.begruessen === ben.begruessen);
console.log(Object.getPrototypeOf(anna) === Benutzer.prototype);
console.log(anna instanceof Benutzer);
Hallo, Anna! true true true

Standardinhalt und fehlende prototype-Eigenschaft

function Punkt() {}
const pfeil = () => {};
const obj = { methode() {} };

console.log(Object.getOwnPropertyNames(Punkt.prototype));
console.log(Punkt.prototype.constructor === Punkt);
console.log(pfeil.prototype);
console.log(obj.methode.prototype);
console.log(Object.getOwnPropertyDescriptor(Punkt, 'prototype'));
[ 'constructor' ] true undefined undefined { value: {}, writable: true, enumerable: false, configurable: false }

Vererbung ohne class-Syntax (und constructor reparieren)

function Tier(name) {
  this.name = name;
}
Tier.prototype.sprechen = function () {
  return `${this.name} macht ein Geräusch.`;
};

function Hund(name) {
  Tier.call(this, name);
}
// Prototypenkette aufbauen
Hund.prototype = Object.create(Tier.prototype);
Hund.prototype.constructor = Hund; // sonst zeigt constructor auf Tier
Hund.prototype.sprechen = function () {
  return `${this.name} bellt.`;
};

const rex = new Hund('Rex');
console.log(rex.sprechen());
console.log(rex instanceof Tier, rex.constructor.name);
Rex bellt. true Hund

Klassen: prototype ist schreibgeschützt

class Konto {
  einzahlen(betrag) { return betrag; }
}

console.log(typeof Konto.prototype.einzahlen);
Konto.prototype = {}; // wird im Sloppy-Mode still ignoriert
console.log(Object.getOwnPropertyNames(Konto.prototype));
console.log(Object.getOwnPropertyDescriptor(Konto, 'prototype').writable);
function [ 'constructor', 'einzahlen' ] false

// Wichtig · Fallstricke

  • Verwechslungsgefahr: fn.prototype ist nicht der Prototyp von fn. Den ermittelt man mit Object.getPrototypeOf(fn) (in der Regel Function.prototype).
  • Ersetzen statt Erweitern: Wer Fn.prototype = { ... } zuweist, verliert die constructor-Eigenschaft und sollte sie wiederherstellen. Bereits erzeugte Instanzen behalten den alten Prototyp, und instanceof liefert für sie danach false.
  • Ist Fn.prototype beim new-Aufruf kein Objekt (z. B. null oder eine Zahl), erhält die Instanz stattdessen Object.prototype als Prototyp.
  • Bei class ist prototype nicht beschreibbar; eine Zuweisung wirft im Strict-Mode (also auch in Modulen und Klassenrümpfen) einen TypeError.
  • Eingebaute Prototypen (Array.prototype, Object.prototype) nicht erweitern: Das kann mit künftigen Standards kollidieren und öffnet Wege für Prototype-Pollution-Angriffe. Beim Zusammenführen nicht vertrauenswürdiger Objekte Schlüssel wie __proto__, constructor und prototype filtern.
  • Methoden auf dem Prototyp sparen Speicher gegenüber Methoden, die im Konstruktor per this.methode = ... für jede Instanz neu angelegt werden.