The chain of prototypes
It’s quite simple actually. Each object has a reference to a prototype, which is always another object, or null
. This object, in turn, also has a prototype. It then forms a prototype chain.
And what’s the point of that? The way it works is similar to the concept of inheritance. Consider the following example: you have an object that represents a vehicle, let’s call it veiculo
. Suppose two other objects, carro
and onibus
, who have veiculo
as a prototype. And suppose veiculo
has a method buzinar
. The prototype chain makes it possible to invoke this method in carro
and onibus
:
carro.buzinar();
onibus.buzinar();
And how does this work? By invoking the method, the interpreter checks whether the object in question (carro
or onibus
) has a method with that name. In this case, objects do not have this method. Then the interpreter checks whether the prototype of each object has the method, and in this case it finds and invokes the method buzinar
. If the method was not found, the interpreter would continue the verification up the prototyping chain until it found the desired method or property, or until it reached an object that has null
as a prototype.
It is important to know that this invocation works as if the method belonged to the object itself; that is, any reference to this
within the method buzinar
will point to carro
or onibus
in this example.
Prototype assignment
The language offers no official way to change the prototype of an object on-the-fly. The prototype is assigned only at the time of the creation of the object, and this can be done in two ways.
1. Assignment via constructor
Every function has a property called prototype
(functions are Javascript objects, so they can have properties). When a function is invoked as a constructor, a new object is created whose prototype is the property value prototype
function. For example:
function Veiculo() {}
Veiculo.prototype.buzinar = function() {
alert('Fom');
}
var carro = new Veiculo(); // invocação como construtor
carro.buzinar(); // dispara o alert
2. Direct allocation
From Ecmascript 5, the language offers another way to create an object with a particular prototype, the function Object.create
. Notice that it is a method of the builder Object
, therefore it can be considered a static method. What this function does is to create a new object whose prototype is what has been passed as the first argument:
var veiculo = {
buzinar: function() {
alert('Fom');
}
};
var carro = Object.create(veiculo); // veiculo será o protótipo de carro
carro.buzinar(); // dispara o alert
3. Allocation on-the-fly
Officially, Javascript does not allow you to change the prototype of existing objects, but major implementations (including all browsers I know) allow this through the non-standard property __proto__
. Using this property is possible to do something like this:
var veiculo = {
buzinar: function() {
alert('Fom');
}
};
var carro = {}; // carro ganha protótipo padrão (Object.prototype)
carro.__proto__ = veiculo; // troca protótipo
carro.buzinar(); // dispara o alert
Notes on the specification
The above explanation is very informal, and similar to what the language specification describes, also informally. But the description contained in the specification may seem a bit confusing, as there are two things called "prototype": the property prototype
of the function-type objects, and the [[Prototype]], which is the official name of the property internal of objects. When the specification uses the term prototype no code formatting or square brackets, usually refers to [[Prototype]], in the same way I used the term prototype in the above description.
As regards access to the prototype chain, the crucial point in the specification is the internal function [[Getproperty]], invoked when you try to access a property of an object. It is a recursive function, which returns the requested property of a given object, whether in the object itself or in one of the members of its prototyping chain.
With the ES6, the prototype has become obsolete?
– Filipe Moraes
No, not at all! The new syntax with
class
is syntactic sugar, the prototype is that it keeps making everything work.– bfavaretto
@bfavaretto, Prototype is a way to reuse methods on other objects?
– felipe cardozo
@felipecardozo Yes, the shared methods belong to the prototype and can be used by any object that is part of the prototype chain.
– bfavaretto
@bfavaretto, thanks a friend!
– felipe cardozo
In relation to this excerpt: "[...] does not allow changing the prototype of existing objects [...]", I think it is appropriate to change, since (relatively) the methods have been introduced recently
Object.setPrototypeOf
andReflect.setPrototypeOf
. The operation[[Set]]
in__proto__
was also once standardised in Annex B to the specification. I was even going to edit it, but I thought I better comment. : P (You can delete this comment later)– Luiz Felipe
Thanks @Luizfelipe. I’ve thought several times about updating this reply, but I’m running out of time. For now stay your comment rs.
– bfavaretto