Javascript prototype chain
Javascript objects have an internal property called [[Prototype]]
for property lookup and inheritance.
When looking for an object property, javascript checks the object's own property first, if not found, it will continue with the object's [[Prototype]]
, if not found again, look for [[Prototype]]
of its [[Prototype]]
until reaching null or the property found.
To access [[Prototype]] of an object:
Object.getPrototypeOf(obj)
,Reflect.getPrototypeOf(obj)
to get.Object.setPrototypeOf(obj, prototype)
,Reflect.setPrototypeOf(obj, prototype)
to set.- [non standard]
Object.prototype.__proto__
getter and setter. - Object initializer syntax with prototype specification:
{__proto__: prototype}
. - Object initializer without prototype specification:
{foo: 'bar'}
set object's[[Prototype]]
toObject.prototype
. Object.create(prototype)
.new Foo
ornew Foo()
create object whose[[Prototype]]
isFoo.prototype
.- Array initializer syntax:
[]
creates object whose[[Prototype]]
isArray.prototype
. - Function definition syntax:
() => {}
,function() {}
create object whose[[Prototype]]
isFunction.prototype
. - RegExp literals
/abc/
creates an object whose[[Prototype]]
isRegExp.prototype
, equivalent ofnew RegExp('abc')
.
Note:
Object initializer with prototype specification is a syntax, it is not the same as Object.prototype.__proto__
setter. Moreover, an object can have its own __proto__
property key.
- The object's
[[Prototype]]
can be set viaobj.__proto__ = prototype
because that object inheritsObject
(its[[Prototype]]
chain hasObject.prototype
), and assigningobj.__proto__
actually callsObject.prototype.__proto__
setter.
Some quirks:
{'__proto__': prototype}
is the same as{__proto__: prototype}
and{"__proto__": prototype}
.{__proto__}
(shorthand property),{['__proto__']: prototype}
,{__proto__(){}}
{get __proto__(){}}
are not prototype specifier syntax, they are typical key-value assignments.{a: 1, a: 2}
gives{a: 2}
(no error), while{__proto__: v1, __proto__: v2}
,{__proto__: v1, '__proto__': v2}
,{'__proto__': v1, '__proto__': v2}
all thow syntax error:Uncaught SyntaxError: Duplicate __proto__ fields are not allowed in object literals
. These are syntax error mean the parser will throw errors even beforev1
,v2
are evaluated.- If the value provided to the prototype specifier is not an object (whose prototype chain contains Object.prototype) or
null
, the specifier is a no-op. JSON.parse('{"__proto__": null}')
returns an object with its own property__proto__
key.
Other notes:
Object.getPrototypeOf(Object.prototype)
isnull
.- You cannot assign a cyclic prototype chain.
Object.setPrototypeOf(a, a)
06:31:41.419 VM410:1 Uncaught TypeError: Cyclic __proto__ value
at Function.setPrototypeOf (<anonymous>)
at <anonymous>:1:8
Object.getPrototypeOf(1) === Number.prototype
returns true because1
is temporarily wrapped bynew Number(1)
(notNumber(1)
which returns the primitive1
value).typeof null
returns"object"
. From MDN web docs:
From MDN web docs:
- functions declared with
function
keyword declaration haveprototype
property. Functions defined with arrow syntax do not have this property.