Los prototipos son un mecanismo en JavaScript que agrega la propiedad a todos los objetos que pueden heredar características de otro objeto. Vamos a profundizar para entender cómo funciona el prototipo y su encadenamiento y cómo puede ser útil.

JavaScript es conocido por ser un lenguaje basado en prototipos. Para que pueda proporcionar herencia a través de cada objeto que contiene un objeto prototipo. El objeto prototipo podría contener la referencia al objeto del cual se deben heredar los métodos y las propiedades. Además, cada objeto prototipo contiene un objeto prototipo que puede heredar aún más los métodos y propiedades. Esto se conoce como una cadena de prototipo.

[[Prototype]]

Los objetos de JavaScript contienen una propiedad oculta – [[Prototype]] (como se menciona en la especificación), que es nula o contiene referencias a otro objeto. Este objeto es el prototipo. Cuando leemos una propiedad del objeto que no existe, el motor de JavaScript busca dentro del prototipo de objetos.

Mira el diagrama de abajo. El objeto A contiene algunas propiedades y métodos. [[Prototype]] del Objeto A contiene una referencia al Objeto B. Por lo tanto, los contenidos del objeto B son accesibles a través del objeto A.

La propiedad – [[Prototype]] está oculta y presente internamente.

__proto__

Hay varias formas de obtener y configurar el prototipo. Usaremos el primitivo __proto__ para entender esto.

__proto__ no es [[Prototype]] sino que es el que lo obtiene y establece.

Podemos ver en el siguiente ejemplo.

let auto = {
  diesel: true
};
let sedan = {
  abs: true
};

auto.__proto__ = sedan; //insertamos el objeto sedan dentro del [[prototype]] auto

// y ahora encontramos ambas propiedades en el objeto sedan now:
alert( sedan.abs ); // true
alert( sedan.diesel ); // true

Tenemos dos objetos, auto y sedán. Aquí podemos ver que el auto ._ proto_ = sedan establece que el sedan sea el prototipo del auto. Por lo tanto, el objeto auto puede acceder a las propiedades del sedan.

Cuando intentamos acceder auto.abs, primero se verifica si la propiedad con el nombre abs está presente. Si no es así, entonces verifica el prototipo de sedán y ahí es donde obtiene el valor.

Veamos otro ejemplo que explica el encadenamiento de prototipos.

let auto = {
  diesel: true,
  verTipo: function() {
    alert("esto es un auto!");
  }
};

let sedan = {
  abs: true,
  __proto__: auto
};

let volkswagen = {
  cuero: true,
  __proto__: sedan
};

volkswagen.verTipo();
alert( volkswagen.volkswagen ); // true
alert( volkswagen.abs ); // true
alert( volkswagen.diesel ); // true

Se ha agregado un nuevo objeto en este caso: Volkswagen, que tiene un sedán como prototipo.

La propiedad prototype

Como sabemos, new func() crea un nuevo objeto con la función constructora. También sabemos que func.prototype es un objeto, lo que significa que el nuevo operador simplemente establece [[Prototype]] para el nuevo objeto.

Veamos el siguiente ejemplo:

let auto = {
  diesel: true
};

function sedan(nombre) {
  this.nombre = nombre;
}

sedan.prototype = auto;

let sedanObj = new sedan("Volkswagen"); // sedanObj.__proto__ == car

alert( sedanObj.diesel ); // true

Establecer sedan.prototype = auto literalmente significa que cuando se crea un nuevo sedán, asigne su [[Prototype]] a auto.

Cada función tiene la propiedad prototipo, incluso si no le asignamos ningún valor.

El prototipo predeterminado de cualquier función es un objeto con el único constructor de propiedades que apunta de nuevo a la función misma.

Categorized in: