Our volunteers haven't translated this article into Tiếng Việt yet. Join us and help get the job done!
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 6 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 6 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 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 2017 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 (ES6) 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.