El patrón prototipo es una forma útil de compartir propiedades entre muchos objetos del mismo tipo. El prototipo es un objeto nativo de JavaScript y los objetos pueden acceder a él a través de la cadena de prototipos.
En nuestras aplicaciones, frecuentemente tenemos que crear muchos objetos del mismo tipo. Una forma útil de hacerlo es creando varias instancias de una clase ES6.
¡Digamos que queremos crear muchos perros! En nuestro ejemplo, los perros no pueden hacer mucho: ¡simplemente tienen un nombre y pueden ladrar!
class Dog {
constructor(name) {
this.name = name;
}
bark() {
return `Woof!`;
}
}
const dog1 = new Dog("Daisy");
const dog2 = new Dog("Max");
const dog3 = new Dog("Spot");
Observe aquí cómo constructor
contiene una name
propiedad y la clase misma contiene una bark
propiedad. Cuando se utilizan clases ES6, todas las propiedades definidas en la propia clase, bark
en este caso, se agregan automáticamente al archivo prototype
.
Podemos verlo prototype
directamente accediendo a la prototype
propiedad en un constructor o mediante la __proto__
propiedad en cualquier instancia .
console.log(Dog.prototype);
// constructor: ƒ Dog(name, breed) bark: ƒ bark()
console.log(dog1.__proto__);
// constructor: ƒ Dog(name, breed) bark: ƒ bark()
¡El valor de __proto__
en cualquier instancia del constructor es una referencia directa al prototipo del constructor! Siempre que intentamos acceder a una propiedad en un objeto que no existe directamente en el objeto, JavaScript bajará por la cadena del prototipo para ver si la propiedad está disponible dentro de la cadena del prototipo.
El patrón prototipo es muy poderoso cuando se trabaja con objetos que deberían tener acceso a las mismas propiedades. En lugar de crear un duplicado de la propiedad cada vez, podemos simplemente agregar la propiedad al prototipo, ya que todas las instancias tienen acceso al objeto prototipo.
Since all instances have access to the prototype, it’s easy to add properties to the prototype even after creating the instances.
Say that our dogs shouldn’t only be able to bark, but they should also be able to play! We can make this possible by adding a play
property to the prototype.
El término cadena prototipo indica que podría haber más de un paso. ¡En efecto! Hasta ahora, sólo hemos visto cómo podemos acceder a propiedades que están directamente disponibles en el primer objeto al que __proto__
se hace referencia. Sin embargo, ¡los propios prototipos también tienen un __proto__
objeto!
¡Creemos otro tipo de perro, un súper perro! Este perro debería heredar todo de un perro normal Dog
, pero también debería poder volar. Podemos crear un súper perro extendiendo la Dog
clase y agregando un fly
método.
class SuperDog extends Dog {
constructor(name) {
super(name);
}
fly() {
return "Flying!";
}
}
¡Creemos un perro volador llamado Daisy
y dejemos que vuele!
Tenemos acceso al bark
método, ya que ampliamos la Dog
clase. ¡El valor de __proto__
en el prototipo de SuperDog
puntos al Dog.prototype
objeto!
Queda claro por qué se llama cadena de prototipos : cuando intentamos acceder a una propiedad que no está directamente disponible en el objeto, JavaScript recorre recursivamente todos los objetos a los que __proto__
apunta, hasta que encuentra la propiedad.
Object.create
El Object.create
método nos permite crear un nuevo objeto, al que podemos pasar explícitamente el valor de su prototipo.
const dog = {
bark() {
return `Woof!`;
},
};
const pet1 = Object.create(dog);
Aunque pet1
no tiene ninguna propiedad, ¡sí tiene acceso a las propiedades en su cadena de prototipos! Como pasamos el dog
objeto como pet1
prototipo, podemos acceder a la bark
propiedad.
const dog = { bark() { console.log(`Woof!`); }};
const pet1 = Object.create(dog);
pet1.bark(); // Woof!console.log("Direct properties on pet1: ", Object.keys(pet1));console.log("Properties on pet1's prototype: ", Object.keys(pet1.__proto__));
¡Perfecto! Object.create
es una forma sencilla de permitir que los objetos hereden directamente propiedades de otros objetos, especificando el prototipo del objeto recién creado. El nuevo objeto puede acceder a las nuevas propiedades recorriendo la cadena del prototipo.
El patrón prototipo nos permite permitir que los objetos accedan y hereden propiedades de otros objetos fácilmente. Dado que la cadena de prototipos nos permite acceder a propiedades que no están definidas directamente en el objeto mismo, podemos evitar la duplicación de métodos y propiedades, reduciendo así la cantidad de memoria utilizada.