Skip to content

Prototypal inheritance #191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

1. `true`, taken from `rabbit`.
2. `null`, taken from `animal`.
3. `undefined`, there's no such property any more.
1. `true`, tomado de `rabbit`.
2. `null`, tomado de `animal`.
3. `undefined`, ya no existe tal propiedad.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Working with prototype
# Trabajando con prototipo

Here's the code that creates a pair of objects, then modifies them.
Aquí está el código que crea un par de objetos, luego los modifica.

Which values are shown in the process?
¿Qué valores se muestran en el proceso?

```js
let animal = {
Expand All @@ -28,4 +28,4 @@ delete animal.jumps;
alert( rabbit.jumps ); // ? (3)
```

There should be 3 answers.
Debería haber 3 respuestas.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

1. Let's add `__proto__`:
1. Agreguemos `__proto__`:

```js run
let head = {
Expand Down Expand Up @@ -27,6 +27,6 @@
alert( table.money ); // undefined
```

2. In modern engines, performance-wise, there's no difference whether we take a property from an object or its prototype. They remember where the property was found and reuse it in the next request.
2. En los motores modernos, en términos de rendimiento, no hay diferencia si tomamos una propiedad de un objeto o su prototipo. Recuerdan dónde se encontró la propiedad y la reutilizan en la siguiente solicitud.

For instance, for `pockets.glasses` they remember where they found `glasses` (in `head`), and next time will search right there. They are also smart enough to update internal caches if something changes, so that optimization is safe.
Por ejemplo, para `pockets.glasses` recuerdan dónde encontraron `glasses` (en `head`), y la próxima vez buscarán allí. También son lo suficientemente inteligentes como para actualizar cachés internos si algo cambia, de modo que la optimización sea segura.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Searching algorithm
# Algoritmo de búsqueda

The task has two parts.
La tarea tiene dos partes.

Given the following objects:
Dados los siguientes objetos:

```js
let head = {
Expand All @@ -27,5 +27,5 @@ let pockets = {
};
```

1. Use `__proto__` to assign prototypes in a way that any property lookup will follow the path: `pockets` -> `bed` -> `table` -> `head`. For instance, `pockets.pen` should be `3` (found in `table`), and `bed.glasses` should be `1` (found in `head`).
2. Answer the question: is it faster to get `glasses` as `pockets.glasses` or `head.glasses`? Benchmark if needed.
1. Use `__proto__` para asignar prototipos de manera que cualquier búsqueda de propiedades siga la ruta: `pockets` -> `bed` -> `table` -> `head`. Por ejemplo, `pockets.pen` debería ser` 3` (que se encuentra en `table`), y `bed.glasses` debería ser `1` (que se encuentra en `head`).
2. Responda la pregunta: ¿es más rápido obtener `glasses` como `pockets.glasses` o `head.glasses`? Referencie si es necesario.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
**The answer: `rabbit`.**
**La respuesta es: `rabbit`.**

That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`.
Esto se debe a que `this` es un objeto antes del punto, por lo que `rabbit.eat()` modifica `rabbit`.

Property lookup and execution are two different things.

The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`.
La búsqueda y ejecución de propiedades son dos cosas diferentes.

El método `rabbit.eat` se encuentra primero en el prototipo, luego se ejecuta con `this = rabbit`.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Where does it write?
# ¿Donde escribe?

We have `rabbit` inheriting from `animal`.
Tenemos `rabbit` heredando de `animal`.

If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`?
Si llamamos a `rabbit.eat()`, ¿qué objeto recibe la propiedad `full`: `animal` o `rabbit`?

```js
let animal = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
Let's look carefully at what's going on in the call `speedy.eat("apple")`.
Echemos un vistazo a lo que sucede en la llamada `speedy.eat("manzana")`.

1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot).
1. El método `speedy.eat` se encuentra en el prototipo (`=hamster`), luego se ejecuta con `this=speedy` (el objeto antes del punto).

2. Then `this.stomach.push()` needs to find `stomach` property and call `push` on it. It looks for `stomach` in `this` (`=speedy`), but nothing found.
2. Entonces `this.stomach.push()` necesita encontrar la propiedad `stomach` y llamar a `push` sobre ella. Busca `stomach` en `this` (`=speedy`), pero no se encuentra nada.

3. Then it follows the prototype chain and finds `stomach` in `hamster`.
3. Luego sigue la cadena del prototipo y encuentra `stomach` en `hamster`.

4. Then it calls `push` on it, adding the food into *the stomach of the prototype*.
4. Luego se llama 'push' en él, agregando la comida en *el stomach del prototipo*.

So all hamsters share a single stomach!
¡Así que todos los hámsters comparten un solo estómago!

Both for `lazy.stomach.push(...)` and `speedy.stomach.push()`, the property `stomach` is found in the prototype (as it's not in the object itself), then the new data is pushed into it.
Tanto para `lazy.stomach.push(...)` como para `speedy.stomach.push ()`, la propiedad `stomach` se encuentra en el prototipo (ya que no está en el objeto mismo), entonces los nuevos datos son empujado hacia dentro.

Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`:
Tenga en cuenta que tal cosa no sucede en caso de una asignación simple `this.stomach=`:

```js run
let hamster = {
stomach: [],

eat(food) {
*!*
// assign to this.stomach instead of this.stomach.push
// asigna a this.stomach en lugar de this.stomach.push
this.stomach = [food];
*/!*
}
Expand All @@ -34,17 +34,17 @@ let lazy = {
__proto__: hamster
};

// Speedy one found the food
speedy.eat("apple");
alert( speedy.stomach ); // apple
// Speedy encontró la comida
speedy.eat("manzana");
alert( speedy.stomach ); // manzana

// Lazy one's stomach is empty
alert( lazy.stomach ); // <nothing>
// El estomago de Lazy está vacio
alert( lazy.stomach ); // <nada>
```

Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object.
Ahora todo funciona bien, porque `this.stomach =` no realiza una búsqueda de `stomach`. El valor se escribe directamente en el objeto `this`.

Also we can totally avoid the problem by making sure that each hamster has their own stomach:
También podemos evitar totalmente el problema asegurándonos de que cada hámster tenga su propio estómago:

```js run
let hamster = {
Expand All @@ -69,12 +69,11 @@ let lazy = {
*/!*
};

// Speedy one found the food
speedy.eat("apple");
alert( speedy.stomach ); // apple
// Speedy encontró la comida
speedy.eat("manzana");
alert( speedy.stomach ); // manzana

// Lazy one's stomach is empty
alert( lazy.stomach ); // <nothing>
// El estómago de Lazy está vacio
alert( lazy.stomach ); // <nada>
```

As a common solution, all properties that describe the state of a particular object, like `stomach` above, should be written into that object. That prevents such problems.
Como solución común, todas las propiedades que describen el estado de un objeto en particular, como el "stomach" anterior, deben escribirse en ese objeto. Eso evita tales problemas.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Why are both hamsters full?
# ¿Por qué están llenos los dos hámsters?

We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object.
Tenemos dos hámsters: `speedy` y `lazy` heredando del objeto `hamster` general.

When we feed one of them, the other one is also full. Why? How can we fix it?
Cuando alimentamos a uno de ellos, el otro también está lleno. ¿Por qué? ¿Cómo podemos arreglarlo?

```js run
let hamster = {
Expand All @@ -25,11 +25,11 @@ let lazy = {
__proto__: hamster
};

// This one found the food
speedy.eat("apple");
alert( speedy.stomach ); // apple
// Este encontró la comida
speedy.eat("manzana");
alert( speedy.stomach ); // manzana

// This one also has it, why? fix please.
alert( lazy.stomach ); // apple
// Este también lo tiene, ¿por qué? arreglar por favor.
alert( lazy.stomach ); // manzana
```

Loading