W3cubDocs

/JavaScript

Object.setPrototypeOf()

The Object.setPrototypeOf() method sets the prototype (i.e., the internal [[Prototype]] property) of a specified object to another object or null.

Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, currently a very slow operation in every browser and JavaScript engine. In addition, the effects of altering inheritance are subtle and far-flung, and are not limited to the time spent in the Object.setPrototypeOf(...) statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. You can read more in JavaScript engine fundamentals: optimizing prototypes.

Because this feature is a part of the language, it is still the burden on engine developers to implement that feature performantly (ideally). Until engine developers address this issue, if you are concerned about performance, you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().

Syntax

Object.setPrototypeOf(obj, prototype)

Parameters

obj

The object which is to have its prototype set.

prototype

The object's new prototype (an object or null).

Return value

The specified object.

Exceptions

TypeError

Thrown if one of the following conditions is met:

Description

Object.setPrototypeOf() is generally considered the proper way to set the prototype of an object. You should always use it in favor of the deprecated Object.prototype.__proto__ accessor.

If the obj parameter is not an object (e.g. number, string, etc.), this method does nothing.

For security concerns, there are certain built-in objects that are designed to have an immutable prototype. This prevents prototype pollution attacks, especially proxy-related ones. The core language only specifies Object.prototype as an immutable prototype exotic object, whose prototype is always null. In browsers, window and location are two other very common examples.

Object.isExtensible(Object.prototype); // true; you can add more properties
Object.setPrototypeOf(Object.prototype, {}); // TypeError: Immutable prototype object '#<Object>' cannot have their prototype set

Examples

Pseudoclassical inheritance using Object.setPrototypeOf

Inheritance in JS using classes.

class Human {}
class SuperHero extends Human {}

const superMan = new SuperHero();

However, if we want to implement subclasses without using class, we can do the following:

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())

The similarity between classical inheritance (with classes) and pseudoclassical inheritance (with constructors' prototype property) as done above is mentioned in Inheritance chains.

In the example below, which also uses classes, SuperHero is made to inherit from Human without using extends by using setPrototypeOf instead.

Warning: It is not advisable to use setPrototypeOf instead of extends due to performance and readability reasons.

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();

Subclassing without extends is mentioned in ES-6 subclassing.

Specifications

Browser compatibility

Desktop Mobile Server
Chrome Edge Firefox Internet Explorer Opera Safari WebView Android Chrome Android Firefox for Android Opera Android Safari on IOS Samsung Internet Deno Node.js
setPrototypeOf
34
12
31
11
21
9
37
34
31
21
9
2.0
1.0
0.12.0

See also

© 2005–2022 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf