Cuando empecé a estudiar Javascript y POO escuché muchas veces que a pesar de que Javascript es un lenguaje orientado a objetos no está basado en clases sino en prototipos.
En este artículo intentaremos entender qué significa exactamente esto y por qué es importante saber qué hace un prototipo.
En otros lenguajes orientados a objetos cuando declaramos una clase estamos creando un nuevo tipo de dato compuesto, es decir, un tipo de dato formado por tipos primitivos. Pero esto no es lo que ocurre en Javascript, a pesar de que desde ES2015 usemos la palabra reservada class. Los prototipos son instancias de objetos. Mientras que las clases son modelos, los objetos heredan directamente de otros objetos por defecto en JS.
Entonces, primero que nada tenemos que entender qué es la cadena de prototipos.
La cadena de prototipos es una estructura en forma de árbol que conecta funcionalidades entre objetos y en cuya raíz se encuentra Object.prototype. Object.prototype provee de una serie de métodos que aparecen en todos los objetos, como por ejemplo toString( ), hasOwnProperty( ) o keys( ).
Prácticamente todos los objetos en Javascript son instancias de Object si seguimos la cadena de prototipos. Y como probablemente ya sabes, casi todo es un objeto en Javascript. Incluso algunos tipos de datos primitivos (string, number y boolean específicamente) pueden ser objetos por fracciones muy pequeñas de tiempo. Entonces, los arrays son objetos, las funciones son objetos y, por supuesto, los objetos son objetos.
La cadena prototipal nos permite crear instancias de arrays, por ejemplo, que tengan acceso a todos los métodos definidos en Array.prototype como map, forEach, filter y un gran etc. Pero también obtenemos acceso a todos los métodos disponibles en Object.prototype.
Pero, ¿cómo ocurre esto?
Pues resulta que todos los objetos en Javascript tienen una propiedad oculta llamada __proto__ que guarda una referencia al objeto prototype del constructor. Siguiendo con el ejemplo de los arrays, un array tiene acceso a todos los métodos en Object.prototype porque cada array individual es una instancia del objeto Array, y el objeto Array es una instancia del objeto Object. Y esta cadena continúa hasta que llegamos al prototipo de Object.prototype, que será null.
De esta manera, cuando intentamos ejecutar un método en un objeto, Javascript primero buscará en las propiedades del objeto en cuestión. Si no encuentra una propiedad con ese nombre buscará en su propiedad __proto__, que guarda una referencia al objeto prototype de su constructor. Si no la encuentra ahí buscará en la propiedad __proto__ del objeto constructor. Esto continuará hasta que encuentre esa propiedad o método, o no la encuentre y lance un TypeError.
Por si acaso, ya que estamos usando los arrays como ejemplo, cabe recordar que los arrays son azúcar sintáctico en Javascript. Son objetos con un comportamiento especial, pero bajo la alfombra son algo así:
{
‘0’: value,
‘1’: value,
‘2’: value
}
Lo que esto significa es que, por ejemplo, cada vez que declaramos un array estamos creando una instancia del objeto Array que viene con el lenguaje. Si lo miramos en consola veremos que la propiedad __proto__ está vinculada al objeto Array:
Y si seguimos metiéndonos en la madriguera veremos que el objeto __proto__ tiene también una propiedad __proto__ que guarda una referencia a Object.prototype (es una referencia aunque nos salga en consola todo, porque ya sabes, DRY).
Entonces, ¿hay alguna forma de crear un objeto sin prototipo en Javascript?
Pues sí, la hay. Resulta que una de las formas que tenemos de crear objetos es con Object.create( ), a la cual podemos pasarle como argumento el objeto que queremos que sea el prototipo del nuevo objeto que queremos crear. Si le pasamos null estaremos creando un objeto que sea solo eso, una hash table:
const objetoSinPrototipo = Object.create(null);
Top comments (0)