Skip to content

F.prototype #208

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,20 +1,20 @@

Answers:
Riposte:

1. `true`.

The assignment to `Rabbit.prototype` sets up `[[Prototype]]` for new objects, but it does not affect the existing ones.
L'assegnazione a `Rabbit.prototype` imposta `[[Prototype]]` per i nuovi oggetti, ma non influenza gli oggetti già esistenti.

2. `false`.

Objects are assigned by reference. The object from `Rabbit.prototype` is not duplicated, it's still a single object referenced both by `Rabbit.prototype` and by the `[[Prototype]]` of `rabbit`.
Gli oggetti vengono assegnati per riferimento. L'oggetto in `Rabbit.prototype` non viene duplicato, è sempre un oggetto riferito sia da `Rabbit.prototype` che da `[[Prototype]]` di `rabbit`.

So when we change its content through one reference, it is visible through the other one.
Quindi quando cambiamo il suo contenuto tramite un riferimento, questo sarà visibile anche attraverso l'altro.

3. `true`.

All `delete` operations are applied directly to the object. Here `delete rabbit.eats` tries to remove `eats` property from `rabbit`, but it doesn't have it. So the operation won't have any effect.
Tutte le operazion di `delete` vengono applicate direttamente all'oggetto. Qui `delete rabbit.eats` prova a rimuovere la proprietà `eats` da `rabbit`, ma non esiste. Quindi l'operazione non avrà alcun effetto.

4. `undefined`.

The property `eats` is deleted from the prototype, it doesn't exist any more.
La proprietà `eats` viene rimossa da prototype, non esiste più.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Changing "prototype"
# Cambiare "prototype"

In the code below we create `new Rabbit`, and then try to modify its prototype.
Nel codice sotto, andiamo a creare `new Rabbit`, e successivamente proviamo a modificare il suo prototype.

In the start, we have this code:
Inizialmente, abbiamo questo codice:

```js run
function Rabbit() {}
Expand All @@ -20,7 +20,7 @@ alert( rabbit.eats ); // true
```


1. We added one more string (emphasized). What will `alert` show now?
1. Aggiungiamo una o più stringhe. Cosa mostrerà `alert` ora?

```js
function Rabbit() {}
Expand All @@ -37,7 +37,7 @@ alert( rabbit.eats ); // true
alert( rabbit.eats ); // ?
```

2. ...And if the code is like this (replaced one line)?
2. ...E se il codice è come il seguente (abbiamo rimpiazzato una sola riga)?

```js
function Rabbit() {}
Expand All @@ -54,7 +54,7 @@ alert( rabbit.eats ); // true
alert( rabbit.eats ); // ?
```

3. And like this (replaced one line)?
3. E in questo caso (abbiamo rimpiazzato solo una riga)?

```js
function Rabbit() {}
Expand All @@ -71,7 +71,7 @@ alert( rabbit.eats ); // true
alert( rabbit.eats ); // ?
```

4. The last variant:
4. L'ultima variante:

```js
function Rabbit() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
We can use such approach if we are sure that `"constructor"` property has the correct value.
Possiamo utilizzare questo approccio se siamo sicuri che il `"constructor"` possiede il valore corretto.

For instance, if we don't touch the default `"prototype"`, then this code works for sure:
Ad esempio, se non tocchiamo il `"prototype"` di default, allora il codice funzionerà di sicuro:

```js run
function User(name) {
Expand All @@ -10,14 +10,14 @@ function User(name) {
let user = new User('John');
let user2 = new user.constructor('Pete');

alert( user2.name ); // Pete (worked!)
alert( user2.name ); // Pete (ha funzionato!)
```

It worked, because `User.prototype.constructor == User`.
Ha funzionato, poiché `User.prototype.constructor == User`.

..But if someone, so to speak, overwrites `User.prototype` and forgets to recreate `constructor` to reference `User`, then it would fail.
..Ma se qualcuno, per un qualsiasi motivo, sovrascrivesse `User.prototype` e dimenticasse di ricreare il `constructor` di riferimento a `User`, allora fallirebbe.

For instance:
Ad esempio:

```js run
function User(name) {
Expand All @@ -33,12 +33,12 @@ let user2 = new user.constructor('Pete');
alert( user2.name ); // undefined
```

Why `user2.name` is `undefined`?
Perché `user2.name` è `undefined`?

Here's how `new user.constructor('Pete')` works:
Ecco come `new user.constructor('Pete')` funziona:

1. First, it looks for `constructor` in `user`. Nothing.
2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has nothing.
3. The value of `User.prototype` is a plain object `{}`, its prototype is `Object.prototype`. And there is `Object.prototype.constructor == Object`. So it is used.
1. Prima, controlla se esiste `constructor` in `user`. Niente.
2. Successivamente segue la catena di prototype. Il prototype di `user` è `User.prototype`, e anche qui non c'è nulla.
3. Il valore di `User.prototype` è un oggetto semplice `{}`, il suo prototype è `Object.prototype`. E c'è un `Object.prototype.constructor == Object`. Quindi verrà utilizzato.

At the end, we have `let user2 = new Object('Pete')`. The built-in `Object` constructor ignores arguments, it always creates an empty object, similar to `let user2 = {}`, that's what we have in `user2` after all.
In conclusione, abbiamo `let user2 = new Object('Pete')`. Il costruttore integrato di `Object` ignora gli argomenti, crea sempre un oggetto vuoto, in maniera simile a `let user2 = {}`, questo è ciò che abbiamo in `user2` alla fine di tutto.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ importance: 5

---

# Create an object with the same constructor
# Crea un oggetto con lo stesso costruttore

Imagine, we have an arbitrary object `obj`, created by a constructor function -- we don't know which one, but we'd like to create a new object using it.
Immagina di avere un oggetto arbitrario `obj`, creato da un costruttore -- non sappiamo quale, ma vorremmo poter creare un nuovo oggetto utilizzandolo.

Can we do it like that?
Possiamo farlo in questo modo?

```js
let obj2 = new obj.constructor();
```

Give an example of a constructor function for `obj` which lets such code work right. And an example that makes it work wrong.
Fornite un esempio di costruttore per `obj` che permetta a questo codice di funzionare correttamente. Ed un esempio che non lo farebbe funzionare.
90 changes: 45 additions & 45 deletions 1-js/08-prototypes/02-function-prototype/article.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# F.prototype

Remember, new objects can be created with a constructor function, like `new F()`.
Ricordate, nuovi oggetti possono essere creati con un costruttore, come `new F()`.

If `F.prototype` is an object, then the `new` operator uses it to set `[[Prototype]]` for the new object.
Se `F.prototype` è un oggetto, l'operatore `new` si prenderà cura di impostare `[[Prototype]]` per il nuovo oggetto.

```smart
JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language.
JavaScript supporta la prototypal inheritance fin dall'inizio. Fu una delle caratteristiche principali del linguaggio.

But in the old times, there was no direct access to it. The only thing that worked reliably was a `"prototype"` property of the constructor function, described in this chapter. So there are many scripts that still use it.
Ma all'inizio non c'era un accesso diretto. L'unica cosa su cui ci si poteva affidare era la proprietà `"prototype"` del costruttore, descritta in questo capitolo. Per questo, esistono ancora molti script che ne fanno utilizzo.
```

Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name.
Da notare che qui `F.prototype` , sta per una comune proprietà chiamata `"prototype"` in `F`. Sembra molto simile al termine "prototype", ma in questo caso intendiamo realmente riferirci ad una proprietà con questo nome.

Here's the example:
Vediamo qui un esempio:

```js run
let animal = {
Expand All @@ -32,27 +32,27 @@ let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
alert( rabbit.eats ); // true
```

Setting `Rabbit.prototype = animal` literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]` to `animal`".
Impostare `Rabbit.prototype = animal` fa letteralmente quanto segue: "Quando un nuovo `new Rabbit` viene creato, assegna il suo `[[Prototype]]` ad `animal`".

That's the resulting picture:
Questo è il risultato:

![](proto-constructor-animal-rabbit.svg)

On the picture, `"prototype"` is a horizontal arrow, meaning a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`.
In figura, `"prototype"` è una freccia orrizzontale, ciò significa che è una comune proprietà, mentre `[[Prototype]]` è verticale, quindi `rabbit` eredita da `animal`.

```smart header="`F.prototype` only used at `new F` time"
`F.prototype` property is only used when `new F` is called, it assigns `[[Prototype]]` of the new object.
```smart header="`F.prototype` viene utilizzato solamente al momento in cui si invoca `new F`"
`F.prototype` viene utilizzata solamente quando si invoca `new F`, e si occupa di assegnare `[[Prototype]]` del nuovo oggetto.

If, after the creation, `F.prototype` property changes (`F.prototype = <another object>`), then new objects created by `new F` will have another object as `[[Prototype]]`, but already existing objects keep the old one.
Se, dopo la creazione, `F.prototype` cambia (`F.prototype = <another object>`), allora verrà creato un nuovo oggetto con `new F` che avrà un altro oggetto come `[[Prototype]]`, ma gli oggetti già esistenti faranno riferimento a quello vecchio.
```

## Default F.prototype, constructor property
## Default F.prototype, la proprietà constructor

Every function has the `"prototype"` property even if we don't supply it.
Ogni funzione possiede la proprietà `"prototype"` anche se non gliela forniamo direttamente.

The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
Il `"prototype"` di default è un oggetto con un'unica proprietà, il `constructor` che punta alla funzione stessa.

Like this:
Vediamo un esempio:

```js
function Rabbit() {}
Expand All @@ -64,33 +64,33 @@ Rabbit.prototype = { constructor: Rabbit };

![](function-prototype-constructor.svg)

We can check it:
Possiamo verificarlo:

```js run
function Rabbit() {}
// by default:
// di default:
// Rabbit.prototype = { constructor: Rabbit }

alert( Rabbit.prototype.constructor == Rabbit ); // true
```

Naturally, if we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`:
Naturalmente, se non facciamo nulla, il `constructor` sarà disponibile a tutti i `rabbit` attraverso `[[Prototype]]`:

```js run
function Rabbit() {}
// by default:
// di default:
// Rabbit.prototype = { constructor: Rabbit }

let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
let rabbit = new Rabbit(); // eredita da {constructor: Rabbit}

alert(rabbit.constructor == Rabbit); // true (from prototype)
alert(rabbit.constructor == Rabbit); // true (dal prototype)
```

![](rabbit-prototype-constructor.svg)

We can use `constructor` property to create a new object using the same constructor as the existing one.
Possiamo utilizzare il `constructor` per creare un nuovo oggetto utilizzando lo stesso costruttore dell'oggetto già esistente.

Like here:
Come nell'esempio:

```js run
function Rabbit(name) {
Expand All @@ -105,17 +105,17 @@ let rabbit2 = new rabbit.constructor("Black Rabbit");
*/!*
```

That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind.
Questo torna molto utile quando abbiamo un oggetto, ma non sappiamo quale costruttore è stato utilizzato (ad esempio se arriva da una libreria di terze parti), e abbiamo bisogno di crearne un altro dello stesso tipo.

But probably the most important thing about `"constructor"` is that...
Ma probabilmente la cosa più importante del `"constructor"` è che...

**...JavaScript itself does not ensure the right `"constructor"` value.**
**...JavaScript stesso non garantisce il giusto valore del `"constructor"`.**

Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
E' vero, esiste di default nel `"prototype"` delle funzioni, ma questo è tutto. Ciò che accade dopo -- è solo nostra responsabilità.

In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
In particolare, se rimpiazziamo completamente il prototype di default, allora non ci sarà alcun `"constructor"`.

For instance:
Ad esempio:

```js run
function Rabbit() {}
Expand All @@ -129,18 +129,18 @@ alert(rabbit.constructor === Rabbit); // false
*/!*
```

So, to keep the right `"constructor"` we can choose to add/remove properties to the default `"prototype"` instead of overwriting it as a whole:
Quindi, per mantenere il `"constructor"` corretto, possiamo decidere di aggiungere/rimuovere proprietà al `"prototype"` di default, invece che sovrascriverlo completamente:

```js
function Rabbit() {}

// Not overwrite Rabbit.prototype totally
// just add to it
// Non sovrascriviamo Rabbit.prototype completamente
// aggiungiamo semplicemente una proprietà
Rabbit.prototype.jumps = true
// the default Rabbit.prototype.constructor is preserved
// il Rabbit.prototype.constructor viene cosi preservato
```

Or, alternatively, recreate the `constructor` property manually:
O, in alternativa, possiamo ricreare il `constructor` manualmente:

```js
Rabbit.prototype = {
Expand All @@ -150,26 +150,26 @@ Rabbit.prototype = {
*/!*
};

// now constructor is also correct, because we added it
// ora il costruttore è corretto, perché lo abbiamo aggiunto noi
```


## Summary
## Riepilogo

In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it.
In questo capitolo abbiamo descritto brevemente il modo in cui impostare il `[[Prototype]]` per gli oggetti generati tramite il costruttore. Più avanti vedremo dei pattern più avanzati su cui fare affidamento.

Everything is quite simple, just a few notes to make things clear:
Il tutto è abbastanza semplice, solo alcune note per renderlo più chiaro:

- The `F.prototype` property (don't mistake it for `[[Prototype]]`) sets `[[Prototype]]` of new objects when `new F()` is called.
- The value of `F.prototype` should be either an object or `null`: other values won't work.
- The `"prototype"` property only has such a special effect when set on a constructor function, and invoked with `new`.
- La proprietà `F.prototype` (da non confondere con `[[Prototype]]`) imposta `[[Prototype]]` dei nuovi oggetti quando viene invocato `new F()`.
- Il valore di `F.prototype` può essere sia un oggetto che `null`: altri valori verranno ignorati.
- La proprietà `"prototype"` ha un effetto speciale quando impostata in un costruttore, ed invocata con `new`.

On regular objects the `prototype` is nothing special:
Negli oggetti "comuni" la proprietà `prototype` non ha alcun significato speciale:
```js
let user = {
name: "John",
prototype: "Bla-bla" // no magic at all
prototype: "Bla-bla" // nessuna magia
};
```

By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
Di default tutte le funzioni hanno `F.prototype = { constructor: F }`, quindi possiamo ottenere il costruttore di un oggetto accedendo alla sua proprietà `"constructor"`.