How do prototypes work in JavaScript?

49

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

So, I ask: how do prototypes work in JavaScript?

    
asked by Carlos Cinelli 08.05.2014 в 22:02
source

1 answer

44

The chain of prototypes

It's quite simple indeed. Each object has a reference to a prototype , which is always another object, or null . This object, in turn, also has a prototype. A prototype chain is then formed.

And what's the use? The operation is similar to the concept of inheritance. Consider the following example: you have an object that represents a vehicle, let's call it veiculo . Assume yet two other objects, carro and onibus , that have veiculo as a prototype. And suppose veiculo has a buzinar method. The prototype chain makes it possible to invoke this method in carro and onibus :

carro.buzinar();
onibus.buzinar();

And how does this work? When 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 buzinar method. If the method was not found, the interpreter would continue the verification by going up the chain of prototypes until it finds the desired method or property, or until it reaches 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 buzinar method will point to carro or onibus in this example.

Prototype assignment

The language does not offer any official way of changing the prototype of an on-the-fly object. The prototype is assigned only at the time of object creation, 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 value of the prototype property of the 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 assignment

From ECMAScript 5, the language provides another way to create an object with a certain prototype, the Object.create function. Note that it is a constructor Object method, so it can be considered a static method. What this function does is create a new object whose prototype is what was 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. Attribution on-the-fly

Officially, JavaScript does not allow changing the prototype of existing objects, but major implementations (including all browsers I know of) allow this through the non-default property __proto__ . Using this property you can 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

Specification Notes

The above explanation is very informal, and similar to what the language specification describes , also informally. But the description in the specification may seem a little confusing, as there are two things called "prototype": a prototype property of the objects of type function , and the [[Prototype]] , which is the official name of the internal property of the objects. When the specification uses the term prototype without code formatting or brackets, it generally refers to [[Prototype]], just as I used the term prototype in the above description .

As far as access to the prototype chain is concerned, the crucial point in the specification is the internal function [[GetProperty]] , invoked when you try to access a property of an object. This is a recursive function, which returns the requested property of a given object, whether it is in the object itself or in one of its prototype chain members.

    
answered by 08.05.2014 / 22:56
source