Cadena de prototipos

Los prototipos de un objeto en Javascript


Javascript es un lenguaje de programación basado en prototipos. ¿Eso qué significa? A grandes rasgos, significa que cada objeto tiene un «objeto padre», que a su vez tiene otro, y así sucesivamente... hasta llegar al final. Esto se llama cadena de prototipos y es una especie de árbol genealógico de objetos.

Averiguar el prototipo

Entonces, ¿Cómo podemos saber la cadena de prototipos que tiene un objeto? Fácil. Para ello, lo primero es saber que tipo de dato tiene, ya que ese será el primer prototipo de la cadena. Luego, irán apareciendo más prototipos, hasta llegar a null.

El método getPrototypeOf()

El método getPrototypeOf() de Object nos permite obtener el prototipo de cualquier objeto. Observa el siguiente ejemplo para conocer la cadena de prototipos de un objeto:

const text = "Hola";

text.constructor.name;    // "String" (el tipo de dato)

const proto1 = Object.getPrototypeOf(text);
proto1.constructor.name    // String (Prototipo 1)

const proto2 = Object.getPrototypeOf(proto1);
proto2.constructor.name   // Object (Prototipo 2)

const proto3 = Object.getPrototypeOf(proto2);
proto3                    // null (Fin de la cadena)

// Por lo tanto, la cadena de prototipos de este objeto es:
// 'String' > 'Object' > null

Repasemos:

  • 1️⃣ La variable text contiene texto, es decir un tipo de dato primitivo string.
  • 2️⃣ Mediante Object.getPrototypeOf() podemos conocer el prototipo de un objeto.
  • 3️⃣ Su primer prototipo es String.
  • 4️⃣ Su segundo prototipo es Object.
  • 5️⃣ No tiene más prototipos.

Normalmente, los objetos tienen al menos dos prototipos (el propio y Object), sin embargo, otros objetos pueden tener más, o incluso pueden existir algunos casos especiales que no tienen prototipos.

Cadena de prototipos

Si has llegado aquí es que quieres saber más. Veamos algunos ejemplos adicionales. La función getPrototypeChain() devuelve la cadena de prototipos de un objeto. Ahora mismo no es importante el código o la implementación (aunque puedes mirarlo si te apetece en la segunda pestaña), simplemente ten en cuenta que devuelve la cadena de prototipos:

getPrototypeChain("Hola");            // 'String' > 'Object' > null
getPrototypeChain(42);                // 'Number' > 'Object' > null
getPrototypeChain([1, 2, 3]);         // 'Array'  > 'Object' > null
getPrototypeChain(/.+/);              // 'RegExp' > 'Object' > null
getPrototypeChain(new SyntaxError()); // 'SyntaxError' > 'Error' > 'Object' > null
// Función que devuelve la cadena de prototipos de una variable
const getPrototypeChain = (object) => {
  const chain = [];
  let proto = object;
  do {
    proto = Object.getPrototypeOf(proto);
    chain.push(proto?.constructor?.name ?? null);
  } while (proto);
  return chain;
}

Eso sí, para poder tener cadena de prototipos debe ser un objeto. Por ejemplo, casos especiales como null o undefined no tienen prototipos.

El operador instanceof

Ahora que conocemos el concepto de cadena de prototipos también podemos utilizar instanceof para saber si una variable hereda de uno de los tipos que hemos visto en el apartado anterior. Por ejemplo:

const numbers = [1, 2, 3];
getPrototypeChain(numbers);   // ['Array', 'Object', null]

numbers instanceof Array      // true
numbers instanceof Object     // true
numbers instanceof Number     // false
numbers instanceof String     // false

Pero al igual que con vimos con typeof, hay una desventaja. Mientras que typeof sólo sirve para tipos de datos primitivos, instanceof sólo sirve para tipos de datos no primitivos.

Recuerda que el hecho de que Javascript determine los tipos de datos automáticamente no quiere decir que no debamos preocuparnos por ello. A menudo, deberemos conocer el tipo de dato de una variable e incluso necesitaremos convertirla a otros tipos de datos. Más adelante veremos formas de convertir entre tipos de datos.

Los prototipos en Javascript

Ahora lo importante, ¿para que sirve esto? La cadena de prototipos es una lista de los métodos y propiedades que comparte un objeto. Por lo tanto, si un objeto tiene como cadena de prototipos: String y Object, significa que puede ejecutar propiedades y métodos tanto de String como de Object.

Observa el siguiente ejemplo:

const numero = 42;    // Cadena de prototipos: ['Number', 'Object', null]

numero                // Devuelve el número: 42
numero.toString();    // Devuelve el número (como un string): "42"
numero.toFixed(2);    // Formatea el número a dos decimales: "42.00"

El método .toFixed() es un método de los Number para formatear números. Sin embargo, lo realmente interesante es que el método .toString() es un método de los Object, y numero a pesar de ser un Number puede ejecutar este método. Esto es posible porque Number tiene Object en su cadena de prototipos, por lo que comparten métodos.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev