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()
.
Warning: While Object.prototype.__proto__
is supported today in most browsers, its existence and exact behavior has only been standardized in the ECMAScript 2015 specification as a legacy feature to ensure compatibility for web browsers. For better support, it is recommended that only Object.getPrototypeOf()
be used instead.
The __proto__
property of Object.prototype
is an accessor property (a getter function and a setter function) that exposes the internal [[Prototype]]
(either an object or null
) of the object through which it is accessed.
The use of __proto__
is controversial, and has been discouraged. It was never originally included in the EcmaScript language spec, but modern browsers decided to implement it anyway. Only recently, the __proto__
property has been standardized in the ECMAScript 2015 language specification for web browsers to ensure compatibility, so will be supported into the future. It is deprecated in favor of Object.getPrototypeOf
/Reflect.getPrototypeOf
and Object.setPrototypeOf
/Reflect.setPrototypeOf
(though still, setting the [[Prototype]]
of an object is a slow operation that should be avoided if performance is a concern).
The __proto__
property can also be used in an object literal definition to set the object [[Prototype]]
on creation, as an alternative to Object.create()
. See: object initializer / literal syntax.
Syntax
var Circle = function () {}; var shape = {}; var circle = new Circle(); // Set the object prototype. // DEPRECATED. This is for example purposes only. DO NOT DO THIS in real code. shape.__proto__ = circle; // Get the object prototype console.log(shape.__proto__ === circle); // true
var shape = function () { }; var p = { a: function () { console.log('aaa'); } }; shape.prototype.__proto__ = p; var circle = new shape(); circle.a();//aaa console.log(shape.prototype === circle.__proto__);//true //or var shape = function () { }; var p = { a: function () { console.log('a'); } }; var circle = new shape(); circle.__proto__ = p; circle.a(); // a console.log(shape.prototype === circle.__proto__);//false //or function test() { } test.prototype.myname = function () { console.log('myname'); } var a = new test() console.log(a.__proto__ === test.prototype);//true a.myname();//myname //or var fn = function () { }; fn.prototype.myname = function () { console.log('myname'); } var obj = { __proto__: fn.prototype }; obj.myname();//myname
Note: that is two underscores, followed by the five characters "proto", followed by two more underscores.
Description
The __proto__
getter function exposes the value of the internal [[Prototype]]
of an object. For objects created using an object literal, this value is Object.prototype
. For objects created using array literals, this value is Array.prototype
. For functions, this value is Function.prototype
. For objects created using new fun
, where fun
is one of the built-in constructor functions provided by JavaScript (Array
, Boolean
, Date
, Number
, Object
, String
, and so on — including new constructors added as JavaScript evolves), this value is always fun.prototype
. For objects created using new fun
, where fun
is a function defined in a script, this value is the value of fun.prototype
. (That is, if the constructor didn't return an other object explicitly, or the fun.prototype
has been reassigned since the instance was created).
The __proto__
setter allows the [[Prototype]]
of an object to be mutated. The object must be extensible according to Object.isExtensible()
: if it is not, a TypeError
is thrown. The value provided must be an object or null
. Providing any other value will do nothing.
To understand how prototypes are used for inheritance, see guide article Inheritance and the prototype chain.
The __proto__
property is a simple accessor property on Object.prototype
consisting of a getter and setter function. A property access for __proto__
that eventually consults Object.prototype
will find this property, but an access that does not consult Object.prototype
will not find it. If some other __proto__
property is found before Object.prototype
is consulted, that property will hide the one found on Object.prototype
.
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object.prototype.__proto__' in that specification. |
Standard | Included in the (normative) annex for additional ECMAScript legacy features for Web browsers (note that the specification codifies what is already in implementations). |
ECMAScript Latest Draft (ECMA-262) The definition of 'Object.prototype.__proto__' in that specification. |
Draft |
Browser compatibility
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | 11 | (Yes) | (Yes) |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
Compatibility notes
While the ECMAScript 2015 specification dictates that support for __proto__
is required only for web browsers (although being normative), other environments may support it as well for legacy usage.