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, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in obj.__proto__ = ... statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. If you care 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.
Description
Throws a TypeError exception if the object whose [[Prototype]] is to be modified is non-extensible according to Object.isExtensible(). Does nothing if the prototype parameter isn't an object or null (i.e., number, string, boolean, or undefined). Otherwise, this method changes the [[Prototype]] of obj to the new value.
Object.setPrototypeOf() is in the latest ECMAScript 6 standard draft. It is generally considered the proper way to set the prototype of an object, vs. the more controversial Object.prototype.__proto__ property.
Examples
var dict = Object.setPrototypeOf({}, null);
Polyfill
Using the older Object.prototype.__proto__ property, we can easily define Object.setPrototypeOf if it isn't available already:
// Only works in Chrome and FireFox, does not work in IE:
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
obj.__proto__ = proto;
return obj;
}
Appending Prototype Chains
A combination of Object.getPrototypeOf() and Object.prototype.__proto__ permits appending a whole prototype chain to a new prototype object:
/**
*** Object.appendChain(@object, @prototype)
*
* Appends the first non-native prototype of a chain to a new prototype.
* Returns @object (if it was a primitive value it will transformed into an object).
*
*** Object.appendChain(@object [, "@arg_name_1", "@arg_name_2", "@arg_name_3", "..."], "@function_body")
*** Object.appendChain(@object [, "@arg_name_1, @arg_name_2, @arg_name_3, ..."], "@function_body")
*
* Appends the first non-native prototype of a chain to the native Function.prototype object, then appends a
* new Function(["@arg"(s)], "@function_body") to that chain.
* Returns the function.
*
**/
Object.appendChain = function(oChain, oProto) {
if (arguments.length < 2) {
throw new TypeError('Object.appendChain - Not enough arguments');
}
if (typeof oProto !== 'object' && typeof oProto !== 'string') {
throw new TypeError('second argument to Object.appendChain must be an object or a string');
}
var oNewProto = oProto,
oReturn = o2nd = oLast = oChain instanceof this ? oChain : new oChain.constructor(oChain);
for (var o1st = this.getPrototypeOf(o2nd);
o1st !== Object.prototype && o1st !== Function.prototype;
o1st = this.getPrototypeOf(o2nd)
) {
o2nd = o1st;
}
if (oProto.constructor === String) {
oNewProto = Function.prototype;
oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1));
this.setPrototypeOf(oReturn, oLast);
}
this.setPrototypeOf(o2nd, oNewProto);
return oReturn;
}
Usage
First example: Appending a chain to a prototype
function Mammal() {
this.isMammal = 'yes';
}
function MammalSpecies(sMammalSpecies) {
this.species = sMammalSpecies;
}
MammalSpecies.prototype = new Mammal();
MammalSpecies.prototype.constructor = MammalSpecies;
var oCat = new MammalSpecies('Felis');
console.log(oCat.isMammal); // 'yes'
function Animal() {
this.breathing = 'yes';
}
Object.appendChain(oCat, new Animal());
console.log(oCat.breathing); // 'yes'
Second example: Transforming a primitive value into an instance of its constructor and append its chain to a prototype
function MySymbol() {
this.isSymbol = 'yes';
}
var nPrime = 17;
console.log(typeof nPrime); // 'number'
var oPrime = Object.appendChain(nPrime, new MySymbol());
console.log(oPrime); // '17'
console.log(oPrime.isSymbol); // 'yes'
console.log(typeof oPrime); // 'object'
Third example: Appending a chain to the Function.prototype object and appending a new function to that chain
function Person(sName) {
this.identity = sName;
}
var george = Object.appendChain(new Person('George'),
'console.log("Hello guys!!");');
console.log(george.identity); // 'George'
george(); // 'Hello guys!!'
Specifications
| Specification | Status | Comment |
|---|---|---|
| ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object.setProtoypeOf' in that specification. |
Standard | Initial definition. |
| ECMAScript 2017 Draft (ECMA-262) The definition of 'Object.setProtoypeOf' in that specification. |
Draft |
Browser compatibility
| Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| Basic support | 34 | 31 (31) | 11 | (Yes) | 9 |
| Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
|---|---|---|---|---|---|---|
| Basic support | No support | No support | 31.0 (31) | ? | No support | 9 |