Skip to content

Prototypal inheritance #207

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
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`, preso da `rabbit`.
2. `null`, preso da `animal`.
3. `undefined`, non esiste più quella proprietà.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Working with prototype
# Lavorare con prototype

Here's the code that creates a pair of objects, then modifies them.
Il seguente codice crea due oggetti, e successivamente li modifica.

Which values are shown in the process?
Quali valori vengono mostrati nel processo?

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

There should be 3 answers.
Dovrebbero esserci 3 risposte.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

1. Let's add `__proto__`:
1. Aggiungiamo `__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. Nei moderni engine, che valutano la performance, non c'è alcuna differenza tra il prelevare una proprietà dall'oggetto oppure direttamente dal suo prototype. Sono in grado di ricordare da dove è stata presa la proprietà e riutilizzarla alla prossima richiesta.

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.
Ad esempio, per `pockets.glasses` ricordano dove hanno trovato `glasses` (in `head`), quindi la prossima volta la cercheranno proprio li. Sono anche abbastanza intelligenti da aggiornare la cache interna nel caso qualcosa cambi, quindi questa ottimizzazione è sicura.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Searching algorithm
# Algoritmo di ricerca

The task has two parts.
Il task è suddiviso in due parti.

Given the following objects:
Dati i seguenti oggetti:

```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. Utilizza `__proto__` per assegnare il prototypes in modo che la catena segua il percorso: `pockets` -> `bed` -> `table` -> `head`. Ad esempio, `pockets.pen` dovrebbe essere `3` (in `table`), e `bed.glasses` dovrebbe essere `1` (in `head`).
2. Rispondi alla domanda: è più veloce ottenere `glasses` come `pockets.glasses` o come `head.glasses`? Eseguite test se necessario.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
**The answer: `rabbit`.**
**La risposta: `rabbit`.**

That's because `this` is an object before the dot, so `rabbit.eat()` modifies `rabbit`.
Questo perché `this` fa riferimento all'oggetto prima del punto, quindi `rabbit.eat()` modifica `rabbit`.

Property lookup and execution are two different things.
La ricerca della proprietà e la sua esecuzione sono cose differenti.

The method `rabbit.eat` is first found in the prototype, then executed with `this=rabbit`.
Il metodo `rabbit.eat` viene prima cercato nel prototype, e successivamente eseguito 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?
# Dove andrà a scrivere?

We have `rabbit` inheriting from `animal`.
Abbiamo un oggetto `rabbit` che eredita da `animal`.

If we call `rabbit.eat()`, which object receives the `full` property: `animal` or `rabbit`?
Se invochiamo `rabbit.eat()`, quale oggetto riceverà la proprietà `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")`.
Guardiamo attentamente cosa succede nella chiamata `speedy.eat("apple")`.

1. The method `speedy.eat` is found in the prototype (`=hamster`), then executed with `this=speedy` (the object before the dot).
1. Il metodo `speedy.eat` viene trovato nel prototype (`=hamster`), eseguito con `this=speedy` (l'oggetto prima 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. Successivamente `this.stomach.push()` deve trovare la proprietà `stomach` ed invocare `push`. Cerca `stomach` in `this` (`=speedy`), ma non trova nulla.

3. Then it follows the prototype chain and finds `stomach` in `hamster`.
3. Allora segue la catena del prototype e trova `stomach` in `hamster`.

4. Then it calls `push` on it, adding the food into *the stomach of the prototype*.
4. Invoca `push` in `hamster`, aggiungendo il cibo nello *stomaco del prototype*.

So all hamsters share a single stomach!
Quindi tutti i criceti condividono un unico stomaco!

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.
Per entrambi `lazy.stomach.push(...)` e `speedy.stomach.push()`, la proprietà `stomach` viene trovata nel prototype (poiché non si trova negli oggetti), quindi i cambiamenti avvengono li.

Please note that such thing doesn't happen in case of a simple assignment `this.stomach=`:
Da notare che questo non accade nel caso di una semplice assegnazione `this.stomach=`:

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

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

// Speedy one found the food
// Speedy trova il cibo
speedy.eat("apple");
alert( speedy.stomach ); // apple

// Lazy one's stomach is empty
// lo stomaco di Lazy è vuoto
alert( lazy.stomach ); // <nothing>
```

Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object.
Ora tutto funziona bene, perché `this.stomach=` non deve andare alla ricerca di `stomach`. Il valore è scritto direttamente nell'oggetto `this`.

Also we can totally avoid the problem by making sure that each hamster has their own stomach:
Possiamo anche evitare completamente il problema, facendo in modo che ogni criceto abbia il suo stomaco:

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

// Speedy one found the food
// Speedy trova il cibo
speedy.eat("apple");
alert( speedy.stomach ); // apple

// Lazy one's stomach is empty
// lo stomaco di Lazy è vuoto
alert( lazy.stomach ); // <nothing>
```

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.
Come soluzione comune, tutte le proprietà che descrivono un particolare stato dell'oggetto, come `stomach`, dovrebbero essere memorizzate nell'oggetto. In questo modo eviteremo il problema.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Why are both hamsters full?
# Perché entrambi i criceti sono sazi?

We have two hamsters: `speedy` and `lazy` inheriting from the general `hamster` object.
Abbiamo due criceti: `speedy` e `lazy`, che ereditano dall'oggetto `hamster`.

When we feed one of them, the other one is also full. Why? How can we fix it?
Quando nutriamo uno di loro, anche l'altro è sazio. Perché? Come possiamo sistemare il problema?

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

// This one found the food
// Questo ha trovato il cibo
speedy.eat("apple");
alert( speedy.stomach ); // apple

// This one also has it, why? fix please.
// Anche questo lo ha ricevuto, perché? provate a sistemarlo
alert( lazy.stomach ); // apple
```

Loading