How do prototypes work in Javascript?

Asked

Viewed 1,802 times

61

It seems to me that the concept of prototype is fundamental in Javascript and even in several places I have read that is one of its strengths. However, this does not seem such a simple concept to understand for those who come from other languages.

Thus, I ask: how prototypes work in Javascript?

1 answer

57


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?

  • 5

    No, not at all! The new syntax with class is syntactic sugar, the prototype is that it keeps making everything work.

  • @bfavaretto, Prototype is a way to reuse methods on other objects?

  • 1

    @felipecardozo Yes, the shared methods belong to the prototype and can be used by any object that is part of the prototype chain.

  • @bfavaretto, thanks a friend!

  • 1

    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 and Reflect.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)

  • 1

    Thanks @Luizfelipe. I’ve thought several times about updating this reply, but I’m running out of time. For now stay your comment rs.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.