Summary
The __proto__
property is deprecated and should not be used. Object.getPrototypeOf
should be used instead of the __proto__
getter to determine the [[Prototype]] of an object. Mutating the [[Prototype]]
of an object, no matter how this is accomplished, is strongly discouraged, because it is very slow and unavoidably slows down subsequent execution in modern JavaScript implementations. However, Object.setPrototypeOf
is provided in ES6 as a very-slightly-preferred alternative to the __proto__
setter.
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.
Syntax
var proto = obj.__proto__;
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 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
at the time new fun
is evaluated. (That is, if a new value is assigned to fun.prototype
, previously-created fun
instances will continue to have the previous value as their [[Prototype]], and subsequent new fun
calls will use the newly-assigned value as their [[Prototype]]
.)
The Object.getPrototypeOf
function is the preferred way to access the [[Prototype]]
of an object. __proto__
and the __proto__
getter function are deprecated and should not be used.
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.
Mutating the [[Prototype]]
of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation. If you care at all about performance, you should never mutate the [[Prototype]]
of an object, either using this method or using Object.setPrototypeOf
. Instead, create the object with the desired [[Prototype]]
using Object.create
. Furthermore, __proto__
and the __proto__
setter function are deprecated and should not be used.
To understand how prototypes are used for inheritance, see guide article Inheritance and the prototype chain.
There is nothing special about the __proto__
property. It is simply an accessor property -- a property consisting of a getter function and a setter function -- on Object.prototype
. 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
.
var noProto = Object.create(null); print(typeof noProto.__proto__); // undefined print(Object.getPrototypeOf(noProto)); // null noProto.__proto__ = 17; print(noProto.__proto__); // 17 print(Object.getPrototypeOf(noProto)); // null var protoHidden = {}; Object.defineProperty(protoHidden, "__proto__", { value: 42, writable: true, configurable: true, enumerable: true }); print(protoHidden.__proto__); // 42 print(Object.getPrototypeOf(protoHidden) === Object.prototype); // true
Example
In the following, a new instance of Employee
is created, then tested to show that its __proto__
is the same object as its constructor's prototype
.
// Declare a function to be used as a constructor function Employee() { /* initialise instance */ } // Create a new instance of Employee var fred = new Employee(); // Test equivalence fred.__proto__ === Employee.prototype; // true
At this point, fred
inherits from Employee
, however assigning a different object to fred.__proto__
can change that:
// Assign a new object to __proto__ fred.__proto__ = Object.prototype;
Now fred
no longer inherits from Employee.prototype
, but directly from Object.prototype
, and loses the properties it originally inherited from Employee.prototype
.
However, this only applies to extensible
objects, a non–extensible object's __proto__
property cannot be changed:
var obj = {}; Object.preventExtensions(obj); obj.__proto__ = {}; // throws a TypeError
Note that even Object.prototype
's __proto__
property can be redefined as long as the chain leads to null:
var b = {}; Object.prototype.__proto__ = { hi: function () {alert('hi');}, __proto__: null }; b.hi();
If Object.prototype
's __proto__
had not been set to null
, or had not been set to another object whose prototype chain did not eventually lead explicitly to null
, a "cyclic __proto__ value" TypeError would result since the chain must eventually lead to null
(as it normally does on Object.prototype
).
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 6 (ECMA-262) The definition of 'Object.prototype.__proto__' in that specification. |
Draft | Included in the (normative) annex for addtional ECMAScript features for Web browsers (note that the specification codifies what is already in implementations). |
Browser compatibility
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |