Herencia Prototipal en JavaScript con la ayuda de Shingeki no Kyojin
Tags: javascript, programming, oop
Published: 2021-04-03 18:01:48

### Herencia Prototipal en JavaScript y Shingeki no Kyojin

> Disclaimer: No es necesario que hayas visto Shingeki no Kyojin para seguir este post. Aun así es recomendable que tengas visto hasta la tercera temporada de la serie para poder sacar el máximo provecho a esta analogía. Ahora, si no has visto Shingeki no Kyojin, hazte un favor y ve a verla ya!

> Si eres un manga reader, estás de rosas. Puede que incluso veas algunos huecos o errores en la analogía. De ser asi hazmelo saber 😉

Dejemos esto claro. Casi todo en JavaScript es un objeto. Los objetos parten el bacalao en JavaScript. Los objetos serán nuestros **titanes**, esas cosas feas y raras a las que todo el mundo les teme.

Un objeto es una colección de parejas key-value, llamados **propiedades y métodos**

```
const obj = {
  key: 'value',
  fruit: 'apple'
}
```

En Shingeki no Kyojin, tras la muerte de la fundadora [Ymir](https://shingeki-no-kyojin.fandom.com/es/wiki/Ymir_Fritz), su alma se dividió entre nueve **titanes**, que construyeron el imperio de Eldia. Si lo anterior te sonó a chino, no te preocupes. Quédate con la idea de que el [poder de los titanes](https://shingeki-no-kyojin.fandom.com/es/wiki/Poder_de_los_titanes) es algo que se puede **heredar** y que estos nueve titanes provienen de un solo titan fundador o mejor aún, **la progenitora de todos los titanes.**

Aquí una lista de los nueve titanes:

- Titán Fundador
- Titán de Ataque
- Titán Colosal
- Titán Acorazado
- Titán Hembra
- Titán Bestia
- Titán Mandíbula
- Titán Carguero
- Titán Martillo de Guerra (aparece en cuarta temporada)

Volvamos a JavaScript. En este lindo lenguaje casi “todo” es un objeto.
Aquí una lista de todo lo que puede ser un objeto en JavaScript:

- Booleanos (si es definido con la keyword new)
- Numbers (sí es definido con la keyword new)
- Strings (si es definido con la keyword new)
- Dates
- Maths
- Expresiones Regulares
- Arrays
- Functions
- Objects

Seguro notaste que esta última lista contiene **nueve** tipos de objetos. Pero qué curioso 😮

Como ya habíamos dicho, `objetos === titanes`. Más adelante veremos que comparten más que solo su cantidad.

Nuestros nueve titanes:
![Nueve titanes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjsvx68xv7xtw5u1o4dc.png)

Obviamente existen más de nueve titanes en la serie. Estos nueve titanes son conocidos como **titanes cambiantes**. Los demás titanes, los que aterrorizan y comen gente de las murallas, son [titanes puros](https://shingeki-no-kyojin.fandom.com/es/wiki/Titanes). Sus equivalentes en JavaScript serían los valores primitivos, un valor que no tiene ni propiedades ni métodos

- string
- number
- boolean
- null
- undefined

Titanes puros:
![Titanes puros](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tu5xc11lp86swf2q6e3.png)


Esto hace que todos los datos dentro de JavaScript, sean [Sujetos de Ymir](https://shingeki-no-kyojin.fandom.com/es/wiki/Gente_de_Ymir) o dicho de otro modo: _JavaScript representa el imperio de Eldia_

Aveces necesitamos crear objetos que compartan ciertas caracteristicas entre si y que sean faciles de reutilizar.

### Creemos algunos titanes

Si queremos crear un app de titanes, para cada titan necesitamos un objeto que represente dicho titan. En vez de escribir un nuevo objeto por cada titan, usaremos una **función constructura**. Sera nuestra _plantilla_ para los futuros objetos que instanciemos. Esta función nos permite crear objetos con una estructura definida con anterioridad y sus datos seran valores que recibe como parametros

```
function Titan(name, type) {
  this.name = name
  this.type = type
}
```

> La palabra `this` dentro de `Titan` se refiere al nuevo objeto que se esta creando

Cuando creamos la función constructora **Titan**, automaticamente creamos otro objeto oculto llamado **prototype**. Por defecto este objeto contiene una propiedad **constructor**, la cual es una referencia a la función constructura original, **Titan** en nuestro ejemplo

```
> Titan
function Titan(name, type) {...}

> Titan.prototype
{ constructor: function Titan(name, type) {...} }

> Titan.prototype.constructor
function Titan(name, type) {...}

```

Vale, usemos esta función constructura para crear unos cuantos objetos (titanes)

```
const grisha = new Titan('Grisha', 'Attack')

> grisha
{ name: 'Grisha', type: 'Attack'}
```

Vemos las propiedades `name` y `type`. Nuestra variable `grisha` efectivamente es una instancia de la función constructora `Titan`.
Pero hay una propiedad escondida (no enumerable) llamada `__proto__` que luce algo asi:

```
> grisha.__proto__
{ constructor: function Titan(name, type) {...} }

```

Esperen, esto ya lo hemos visto. Es el mismo objeto que `Titan.prototype`. Con ustedes, **Herencia Prototipal**.

```
> grisha.__proto__ === Titan.prototype
true
```

Cuando un nuevo objeto es creado usando una función constructora, este objeto tiene acceso al prototipo de dicha función constructora. Esto crea una cadena de referencia entre el constructor y la instancia, mejor conocida como **prototype chain**

La palabra `new` es muy importante para que esto suceda. Crea un objeto vacio que tenga en su **prototype chain** el prototipo del constructor y despues ejecuta `Titan` con `this` atada a este nuevo objeto.

Se preguntaran que pinta Attack on Titan en todo esto. Aquellos que posean uno de los nueve titanes, cuentan con el poder de los titanes, el poder que se fue heredando entre generaciones despues de la muerte de Ymir.

Este poder permite acceder a las memorias de los individuos que albergaron dicho poder en el pasado. Acceder a los recuerdos de sus predecesores 🤔


Esto me suena de algo, es muy parecido a como los objetos pueden acceder al prototipo de su función constructora. Pero ¿Que vendrian siendo los "recuerdos" para JavaScript en esta analogia?

Supongamos que queramos que nuestros titanes creados con la función `Titan` tengan un metodo llamado `fight`. Podriamos crear esa funcion directamente dentro de `Titan`

```
function Titan(name, type) {
  this.name = name
  this.type = type
  this.fight = function() {
    console.log('Tatakae!')
  }
}
```

Esto funcionaria, cada instancia de este constructor vendria con este metodo `fight`. Estamos compartiendo propiedades y metodos entre objetos, un pilar de la programación orientada a objetos.

Pero hay un problema, esta función interna `fight` se creara por cada nuevo objeto que instanciemos, consumiendo memoria.

Podemos agregarla al objeto `prototype` de nuestro constructor y como las instancias de este constructor pueden acceder a su prototipo por medio de la cadena prototipal, conseguimos el mismo resultado, ahorrando memoria.

```
function Titan(name, type) {
  this.name = name
  this.type = type
}

Titan.prototype.fight = function(value) {
  console.log(value)
}

const eren = new Titan('Eren', 'Attack')

eren.fight('Tatakae!')

```

Nuestro objeto `eren` tiene acceso al metodo `fight` por medio de la cadena prototipal. Incluso hemos hecho a la función mucho mas modular, haciendo que reciba un valor y lo imprima en la pantalla, por si queremos crear otro titan que al pelear grite algo diferente (i.e: `zeke.fight('Leviii!!!')`) 😉

> Es importante notar que `eren.fight` no existe, `eren` no cuenta con ese metodo localmente. `eren` tiene acceso a la función `fight()` localizada en `Titan.prototype` porque `eren` es una instancia de `Titan`. El objeto `eren` puede heredar propiedades y metodos de otro objeto, siendo este otro objeto el prototipo de la función constructora, osea `Titan.prototype`. Esta especie de "link" invisible se le conoce como **Prototype Chain**. El engine de JavaScript usa esta cadena ⛓ para localizar el metodo dentro del objeto prototipo del constructor en caso de que no lo encuentre localmente.

Ahora podemos ver que los "recuerdos" a los cuales tienen acceso los portadores del poder de los titanes son el equivalente a las propiedades y metodos que los objetos usan por medio de la cadena prototipal

> Los portadores del poder de los titanes heredan los recuerdos de sus predecesores

> Los objetos en JavaScript pueden heredar propiedades de otros objetos - de prototipos

![memories](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qojs6ai5wluluydgzybn.png)

Los titanes y objetos heredan cosas de forma muy similar. Genial, esta analogia tiene algo de sentido despues de todo, pero hay mas 😏

¿Que sucede con **Ymir**?
¿Cual es su equivalente en JavaScript?

Volvamos al ejemplo anterior, pero esta vez hagamos que **Eren** herede los recuerdos de su padre **Grisha**, como pasa en la serie.

```
function Titan (name, type) {
  this.name = name
  this.type = type
}

Titan.prototype.fight = function(value) {
  console.log(value)
}

const grisha = new Titan('Grisha', 'Attack')
grisha.fight("I'm a subjet of Ymir!")

const eren = Object.create(grisha)

> eren
{}

> eren.type
Attack

> eren.name
Grisha

> eren.__proto__
{ name: 'Grisha', type: 'Attack' }

eren.name = 'Eren'
> eren.name
Eren

```

En el bloque de code anterior pasaron muchas cosas, vamos a ir paso por paso:

- Creamos nuestra función constructora `Titan` y le agregamos un metodo `fight` a su prototipo

- Creamos a `grisha`, que por ser una instancia de la función constructora `Titan`, tiene acceso a su prototipo (un objeto que hereda de otro objeto) por ende puede usar el metodo `fight`

* Despues creamos a `eren` con la función `Object.create`. Esta función crea un objeto nuevo, utilizando un objeto existente como el prototipo del nuevo objeto creado. Usamos el objeto `grisha` como el **prototipo** del nuevo objeto `eren`

* Si imprimimos `eren` en la consola, podemos ver que es un objeto vacio, aparentemente sin ninguna propiedad 🤨

* Pero si accedemos a `eren.type` o `eren.name` podemos ver los valores 'Attack' y 'Grisha' respectivamente 🤨🤔

* Esta parte es interesante. Como `grisha` se uso como **prototipo** de `eren`, JavaScript al no encontrar `type` o `name` localmente en `eren`, recorre la cadena prototipal y busca dichas propiedades en el prototipo. Eren ha heredado las memorias de su padre por medio de la **cadena prototipal**. Al chequear el prototipo de `eren` podemos ver el objeto del cual va a heredar

> El equivalente de la **cadena prototipal** en Attack on titan son los **caminos**. Los [caminos](https://shingeki-no-kyojin.fandom.com/es/wiki/Caminos) son enlaces invisibles que conectan a los titanes y a la Gente de Ymir 🤯
> Los Caminos funcionan como un medio único para transportar varias cosas (propiedades en JS), desde las memorias de los eldianos hasta la carne, los huesos y demás órganos que componen el cuerpo de un titán (objeto), tanto puro como cambiante. Si volvemos a recordar que `titanes === objetos`, nos queda claro que Hajime Isayama hizo un bootcamp de JavaScript antes de escribir Attack on titan. Todo parece encajar 😅

- Vale, el objeto `eren` hereda propiedades de otro objeto (prototipo). Este es el core de la **Herencia Prototipal**. Pero `eren.name` deberia ser 'Eren', no 'Grisha' asi que creamos esa propiedad dentro de `eren`. `eren.name = 'Eren'`

* Como la propiedad `name` ya existe localmente dentro de `eren`, no tenemos que buscarla en el prototipo. JavaScript ya no buscara dentro de las propiedades heredadas. No recorremos la cadena prototipal, ya no es necesario. Esto es muy importante. Un objeto puede tener propiedades propias (definidas localmente) o propiedades heredadas (definidas en su prototipo)

![Eren inherits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bh94edke2ovr2jp9o5r1.jpg)

Ahora veamos esto

```
> eren.toString()
"[object Object]"
```

Este metodo funciona. Devuelve una cadena de texto que representa al objeto. Pero esperen un momento 🤨

Eren ¿De quien estas heredando este metodo?

Sabemos con certeza de que no es de su padre Grisha, tampoco de la función constructora, nunca pusimos ese metodo ni en el cuerpo de la función ni en el prototipo de la función.

![eren](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv9mj5wg8l8yz56lj4b8.png)

¿De donde viene este metodo?

JavaScirpt puede ser muy obstinado, si no encuentra algo localmente en tu objeto, recorrera la cadena prototipal para buscar en propiedades heredadas definidas en un objeto prototipo. Si no tiene exito en el prototipo de tu objeto, buscara en el prototipo de ese prototipo 🤔 y si no tiene suerte, en el prototipo del prototipo del prototipo 😵 (lo se, es muy confuso) y asi hasta que encuentre lo que estaba buscando o llegue al final de la cadena prototipal 🥴

Usemos el enunciado anterior para recorrer la cadena prototipal que tenemos en nuestro ejemplo.

```
???
⛓
Titan.prototype
⛓
grisha
⛓
eren
```

El objeto `eren` no tiene el metodo `toString`, miremos en su prototipo `grisha`. Nada, `grisha` tampoco cuenta con ese metodo, ahora miremos en el prototipo de `grisha` que si recordamos, es `Titan.prototype`. Nada, solo nos queda mirar en el prototipo de `Titan.prototype` 🤔

`Titan.prototype` es un objeto, por lo que tambien hereda propiedades de otro objeto que hemos pasado por alto. Si inspeccionamos `Titan.prototype` vemos esto:

```
> Titan.prototype
{ constructor: function Titan(name, type) {...},
  fight: function(value) {...}
  __proto__: {...}
}
```

Vale, al principio solo vimos la propiedad **constructor** porque aún no habiamos agregado el metodo `fight`. Pero la propiedad `__prop__` siempre estuvo ahí. Es el **prototipo** del cual `Titan.prototype` hereda. Es una propiedad no enumerable, por lo cual viene escondida y no la habiamos tomado en cuenta, hasta ahora.

Dentro de esta propiedad estan las respuestas que buscamos. Estamos entrando en el sótano de la antigua casa de Eren 😮

![Sótano](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/edrhwbdallsxsn4r16lu.jpg)

```
> Titan.prototype.__proto__
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()

```

> Eso puede verse mejor en la consola de chrome, en node es complicado ver esto

Vemos un montón de propiedades y metodos dentro de este objeto. Recordemos que estamos viendo el prototipo del prototipo de nuestra función constructura `Titan` 😵

![book](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a44rsodqdg2kx5jwk3yz.jpg)

Vemos a la función `toString` que `eren` fue capaz de utilizar hace poco. Genial, ya sabemos de donde proviene. Tambien vemos un `constructor` que hace referencia a la función constructora de este objeto.
Esto quiere decir que el objeto `Titan.prototype` es una instancia del constructor `Object` y al ser una **instancia de un constructor**, este tiene acceso al **prototipo** del _constructor_, osea `Object.prototype`. ¿Confundido? Miremos el siguiente bloque de codigo

```
> Titan.prototype.__proto__ === Object.prototype
true
```

Con ustedes, `Objet.prototype`. El creador, el fundador, el progenitor de todos los objetos 🙇‍♀️🙇‍
Nuestro Titan fundador, la primera Titan cambiante, como vimos al principio del post, **la progenitora de todos los titanes** [Ymir Fritz](https://shingeki-no-kyojin.fandom.com/es/wiki/Ymir_Fritz)

Ymir esta en la cima de la cadena prototipal. Todos nuestros titanes estan heredando propiedades y metodos de ella y todos estan conectados a ella por medio de los _caminos_ (cadena prototipal)

![ymir](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmo2o19n4p3axaalgluw.png)

```
Object.prototype --> Ymir
⛓
Titan.prototype
⛓
grisha
⛓
eren
```

Esta es la razón por la cual somos capaces de usar metodos como `hasOwnProperty`, `toString` o `isPrototypeOf` en objetos vacios. Estan heredando todo de su fundador `Object.prototype` gracias a sendas invisibles, a las que se les dio el nombre de _Caminos_ (cadena prototipal)

![ymir-and-demon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8l1docf058zxfdhu9rxb.png)

> Tambien es posible usar estos metodos en valores que no sean objetos (valores primitivos). Recordemos que todos los datos en JavaScript son eldianos, cada eldiano que existe es solo una pequeña porción del cuerpo del Titán Fundador

Con eso damos fin a esta analogia entre Herencia prototipal y Shingeki no Kyojin. Espero que ahora puedas ver este tema tan confuso con un poco mas claridad. Estoy seguro que si eres fan de la serie, podras entender con mayor facilidad.

Te invito a que creas toda la cadena prototipal basada en los personajes que heredan el titan fundador, algo asi:

```
Ymir
⛓
Karl
⛓
...
⛓
Frieda
⛓
Grisha
⛓
Eren

```

Puedes incluir propiedades locales en cada uno y que despues se puedan heredar, como el color de ojos, habilidades, el tipo y cantidad de titanes que tienen o tuvieron (Eren cuenta con tres titanes, Grisha en un punto tuvo a dos antes de pasarselos a eren).

Tambien puedes crear a los nueve titanes cambiantes, usando la sintaxis de `class` que es _syntax sugar_ que hace mas facil crear los templates e instanciarlos. Puedes tener una clase madre que sea Ymir y otras nueve clases que hereden (`extends`) propiedades de ella, pero con valores propios (habilidades especiales de cada titan)

El objeto de Eren tiene que tener este metodo, obligatoriamente 😉

```
> eren.loves(historia)
false

> eren.loves(mikasa)
true
```

**Shinzou wo Sasageyo!**