JavaScript Object Prototypes
[[Prototype]]
In JavaScript, objects have a special hidden property [[Prototype]]
(as named in the specification), that is either null
or references another object. That object is called “a prototype”:
object -> [[Prototype]] ->
prototype object
When we read a property from object
, and it’s missing, JavaScript automatically takes it from the prototype. In programming, this is called “prototypal inheritance”. And soon we’ll study many examples of such inheritance, as well as cooler language features built upon it.
The property [[Prototype]]
is internal and hidden, but there are many ways to set it.
Now if we read a property from rabbit
, and it’s missing, JavaScript will automatically take it from animal
.
For instance:
let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal; // (*)
// we can find both properties in rabbit now:
alert( rabbit.eats ); // true (**)
alert( rabbit.jumps ); // true
Here the line (*)
sets animal
to be the prototype of rabbit
.
Then, when alert
tries to read property rabbit.eats
(**)
, it’s not in rabbit
, so JavaScript follows the [[Prototype]]
reference and finds it in animal
(look from the bottom up):
let animal = {
eats: true,
walk()
{
console.log("animal walk");
}
};
let rabbit = {
jumps: true,
__proto__:animal
};
console.log(rabbit.eats); // true
console.log(rabbit.jumps); // true
// walk is taken from the prototype
rabbit.walk(); // animal walk
The prototype chain can be longer:
let animal = { eats: true, walk() { alert("Animal walk"); } }; let rabbit = { jumps: true, __proto__: animal }; let longEar = { earLength: 10, __proto__: rabbit }; // walk is taken from the prototype chain longEar.walk(); // Animal walk alert(longEar.jumps); // true (from rabbit)
Writing doesn’t use prototype
The prototype is only used for reading properties.
Write/delete operations work directly with the object.
In the example below, we assign its own walk
method to rabbit
:
let animal = { eats: true, walk() { /* this method won't be used by rabbit */ } }; let rabbit = { __proto__: animal }; rabbit.walk = function() { alert("Rabbit! Bounce-bounce!"); };
From now on, rabbit.walk()
call finds the method immediately in the object and executes it, without using the prototype:
Comments
Post a Comment