Object.setPrototypeOf()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Die Object.setPrototypeOf()
statische Methode setzt das Prototyp (d.h. die interne [[Prototype]]
-Eigenschaft) eines angegebenen Objekts auf ein anderes Objekt oder null
.
Warnung: Das Ändern des [[Prototype]]
eines Objekts ist aufgrund der Art und Weise, wie moderne JavaScript-Engines den Zugriff auf Eigenschaften optimieren, derzeit ein sehr langsamer Vorgang in jedem Browser und jeder JavaScript-Engine. Darüber hinaus sind die Auswirkungen der Änderung der Vererbung subtil und umfangreich und beschränken sich nicht auf die Zeit, die im Object.setPrototypeOf(...)
-Statement verbringt wird, sondern können sich auf jedem Code auswirken, der Zugriff auf ein Objekt hat, dessen [[Prototype]]
geändert wurde. Sie können mehr darüber in JavaScript engine fundamentals: optimizing prototypes lesen.
Da dieses Feature Teil der Sprache ist, liegt die Verantwortung für die performante Implementierung (idealerweise) immer noch bei den Engine-Entwicklern. Bis die Engine-Entwickler dieses Problem angehen, sollten Sie, wenn Sie besorgt über die Leistung sind, vermeiden, das [[Prototype]]
eines Objekts zu setzen. Stattdessen sollten Sie ein neues Objekt mit dem gewünschten [[Prototype]]
unter Verwendung von Object.create()
erstellen.
Probieren Sie es aus
Syntax
Object.setPrototypeOf(obj, prototype)
Parameter
Rückgabewert
Das angegebene Objekt.
Ausnahmen
TypeError
-
Wird in einem der folgenden Fälle ausgelöst:
- Der
obj
-Parameter istundefined
odernull
. - Der
obj
-Parameter ist nicht erweiterbar, oder es handelt sich um ein unveränderliches exotisches Prototypobjekt, wieObject.prototype
oderwindow
. Ein Fehler wird jedoch nicht ausgelöst, wenn der neue Prototyp denselben Wert wie der ursprüngliche Prototyp vonobj
hat. - Der
prototype
-Parameter ist kein Objekt odernull
.
- Der
Beschreibung
Object.setPrototypeOf()
wird im Allgemeinen als die richtige Methode betrachtet, um das Prototyp eines Objekts zu setzen. Sie sollten es immer gegenüber dem veralteten Object.prototype.__proto__
Accessor verwenden.
Wenn der obj
-Parameter kein Objekt ist (z.B. Zahl, String, etc.), macht diese Methode nichts — ohne es zu einem Objekt zu zwingen oder zu versuchen, seinen Prototyp zu setzen — und gibt obj
direkt als primitiven Wert zurück. Wenn prototype
denselben Wert wie das Prototyp von obj
hat, wird obj
direkt zurückgegeben, ohne einen TypeError
zu verursachen, selbst wenn obj
ein unveränderliches Prototyp hat.
Aus Sicherheitsgründen gibt es bestimmte eingebaute Objekte, die ein unveränderliches Prototyp haben sollen. Dies verhindert Angriffe durch Prototyp-Verschmutzung, insbesondere Proxy-bezogene. Die Kernsprache spezifiziert nur Object.prototype
als unveränderliches exotisches Prototypobjekt, dessen Prototyp immer null
ist. In Browsern sind window
und location
zwei weitere sehr häufige Beispiele.
Object.isExtensible(Object.prototype); // true; you can add more properties
Object.setPrototypeOf(Object.prototype, {}); // TypeError: Immutable prototype object '#<Object>' cannot have their prototype set
Object.setPrototypeOf(Object.prototype, null); // No error; the prototype of `Object.prototype` is already `null`
Beispiele
Pseudoklassische Vererbung unter Verwendung von Object.setPrototypeOf()
Vererbung in JS unter Verwendung von Klassen.
class Human {}
class SuperHero extends Human {}
const superMan = new SuperHero();
Wenn wir jedoch Unterklassen ohne class
implementieren wollen, können wir Folgendes tun:
function Human(name, level) {
this.name = name;
this.level = level;
}
function SuperHero(name, level) {
Human.call(this, name, level);
}
Object.setPrototypeOf(SuperHero.prototype, Human.prototype);
// Set the `[[Prototype]]` of `SuperHero.prototype`
// to `Human.prototype`
// To set the prototypal inheritance chain
Human.prototype.speak = function () {
return `${this.name} says hello.`;
};
SuperHero.prototype.fly = function () {
return `${this.name} is flying.`;
};
const superMan = new SuperHero("Clark Kent", 1);
console.log(superMan.fly());
console.log(superMan.speak());
Die Ähnlichkeit zwischen klassischer Vererbung (mit Klassen) und pseudoklassischer Vererbung (mit dem prototype
-Attribut des Konstruktors) wie oben beschrieben wird in Vererbungsketten erwähnt.
Da die prototype
-Eigenschaft von Funktionskonstruktoren beschreibbar ist, können Sie diese auf ein neues Objekt, das mit Object.create()
erstellt wurde, neu zuweisen, um dieselbe Vererbungskette zu erreichen. Es gibt Einschränkungen, auf die Sie bei der Nutzung von create()
achten sollten, wie das Wiedereinfügen der constructor
-Eigenschaft.
Im folgenden Beispiel, das auch Klassen verwendet, wird SuperHero
so erstellt, dass es von Human
erbt, ohne extends
zu verwenden, indem stattdessen setPrototypeOf()
verwendet wird.
Warnung: Es wird nicht empfohlen, setPrototypeOf()
anstelle von extends
zu verwenden, aufgrund von Leistungs- und Lesbarkeitsgründen.
class Human {}
class SuperHero {}
// Set the instance properties
Object.setPrototypeOf(SuperHero.prototype, Human.prototype);
// Hook up the static properties
Object.setPrototypeOf(SuperHero, Human);
const superMan = new SuperHero();
Die Unterklassifizierung ohne extends
wird in ES-6 subclassing erwähnt.
Spezifikationen
Specification |
---|
ECMAScript Language Specification # sec-object.setprototypeof |
Browser-Kompatibilität
BCD tables only load in the browser