Skip to content

Commit e5262d2

Browse files
committed
fix broken articles
1 parent e82621a commit e5262d2

File tree

14 files changed

+381
-1161
lines changed

14 files changed

+381
-1161
lines changed
Lines changed: 93 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11

2-
Let's examine what exactly happens inside `makeArmy`, and the solution will become obvious.
2+
Esaminiamo cosa accade dentro `makeArmy`, e la soluzioni ci apparirà ovvia.
33

4-
1. It creates an empty array `shooters`:
4+
1. Crea un array vuoto `shooters`:
55

66
```js
77
let shooters = [];
88
```
9-
2. Fills it with functions via `shooters.push(function)` in the loop.
9+
2. Lo riempie con un ciclo `shooters.push(function...)`.
1010

11-
Every element is a function, so the resulting array looks like this:
11+
Ogni elemento è una funzione, quindi l'array finale risulterà essere:
1212
1313
```js no-beautify
1414
shooters = [
@@ -25,105 +25,96 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
2525
];
2626
```
2727
28-
3. The array is returned from the function.
29-
30-
Then, later, the call to any member, e.g. `army[5]()` will get the element `army[5]` from the array (which is a function) and calls it.
31-
32-
Now why do all such functions show the same value, `10`?
33-
34-
That's because there's no local variable `i` inside `shooter` functions. When such a function is called, it takes `i` from its outer lexical environment.
35-
36-
Then, what will be the value of `i`?
37-
38-
If we look at the source:
39-
40-
```js
41-
function makeArmy() {
42-
...
43-
let i = 0;
44-
while (i < 10) {
45-
let shooter = function() { // shooter function
46-
alert( i ); // should show its number
47-
};
48-
shooters.push(shooter); // add function to the array
49-
i++;
50-
}
51-
...
52-
}
53-
```
54-
55-
We can see that all `shooter` functions are created in the lexical environment of `makeArmy()` function. But when `army[5]()` is called, `makeArmy` has already finished its job, and the final value of `i` is `10` (`while` stops at `i=10`).
56-
57-
As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`.
58-
59-
![](lexenv-makearmy-empty.svg)
60-
61-
As you can see above, on each iteration of a `while {...}` block, a new lexical environment is created. So, to fix this, we can copy the value of `i` into a variable within the `while {...}` block, like this:
62-
63-
```js run
64-
function makeArmy() {
65-
let shooters = [];
66-
67-
let i = 0;
68-
while (i < 10) {
69-
*!*
70-
let j = i;
71-
*/!*
72-
let shooter = function() { // shooter function
73-
alert( *!*j*/!* ); // should show its number
74-
};
75-
shooters.push(shooter);
76-
i++;
77-
}
78-
79-
return shooters;
80-
}
81-
82-
let army = makeArmy();
83-
84-
// Now the code works correctly
85-
army[0](); // 0
86-
army[5](); // 5
87-
```
88-
89-
Here `let j = i` declares an "iteration-local" variable `j` and copies `i` into it. Primitives are copied "by value", so we actually get an independent copy of `i`, belonging to the current loop iteration.
90-
91-
The shooters work correctly, because the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration:
92-
93-
![](lexenv-makearmy-while-fixed.svg)
94-
95-
Such problem could also be avoided if we used `for` in the beginning, like this:
96-
97-
```js run demo
98-
function makeArmy() {
99-
100-
let shooters = [];
101-
102-
*!*
103-
for(let i = 0; i < 10; i++) {
104-
*/!*
105-
let shooter = function() { // shooter function
106-
alert( i ); // should show its number
107-
};
108-
shooters.push(shooter);
109-
}
110-
111-
return shooters;
112-
}
113-
114-
let army = makeArmy();
115-
116-
army[0](); // 0
117-
army[5](); // 5
118-
```
119-
120-
That's essentially the same, because `for` on each iteration generates a new lexical environment, with its own variable `i`. So `shooter` generated in every iteration references its own `i`, from that very iteration.
121-
122-
![](lexenv-makearmy-for-fixed.svg)
28+
3. L'array viene ritornato dalla funzione.
29+
30+
Successivamente, la chiamata `army[5]()` otterrà l'elemento `army[5]` dall'array (cioè una funzione) e la invocherà.
31+
32+
Ora perchè tutte le funzione mostrano lo stesso risultato?
33+
34+
Questo accade perchè non c'è alcuna variabile locale `i` interna alla funzione `shooter`. Quando questa funzione viene invocata, prende `i` dal lexical environment esterno.
35+
36+
Quale sarà il valore di `i`?
37+
38+
Se guardiamo il codice:
39+
40+
```js
41+
function makeArmy() {
42+
...
43+
let i = 0;
44+
while (i < 10) {
45+
let shooter = function() { // shooter function
46+
alert( i ); // should show its number
47+
};
48+
...
49+
}
50+
...
51+
}
52+
```
53+
54+
...Notiamo che si trova nel lexival environment associato a `makeArmy()`. Ma quando invochiamo `army[5]()`, `makeArmy` ha già terminato l'esecuzione, e `i` possiede l'ultimo valore: `10`.
55+
56+
Il risultato è che tutte le funzioni `shooter` la prendono dallo stesso lexical envrironment esterno, in cui l'ultimo valore è `i=10`.
57+
58+
Questo può essere sistemato molto facilmente:
59+
60+
```js run
61+
function makeArmy() {
62+
63+
let shooters = [];
64+
65+
*!*
66+
for(let i = 0; i < 10; i++) {
67+
*/!*
68+
let shooter = function() { // shooter function
69+
alert( i ); // should show its number
70+
};
71+
shooters.push(shooter);
72+
}
73+
74+
return shooters;
75+
}
76+
77+
let army = makeArmy();
78+
79+
army[0](); // 0
80+
army[5](); // 5
81+
```
82+
Ora funziona correttamente, perché ogni volta che viene eseguito il blocco di codice `for (..) {...}`, viene creato un nuovo Lexical Environment, con il corrispondente valore `i`.
83+
84+
Quindi, il valore di `i` ora si trova più "vicino". Non più nel lexical environment di `makeArmy()`, ma in quello del corrispondente ciclo. Uno `shooter` preleva il valore esattamente da dove è stato creato.
85+
86+
![](lexenv-makearmy.svg)
87+
88+
Qui abbiamo riscritto `while` in `for`.
89+
90+
Eì possibile farlo in un altro modo, vediamolo per capirlo meglio:
91+
92+
93+
```js run
94+
function makeArmy() {
95+
let shooters = [];
96+
97+
let i = 0;
98+
while (i < 10) {
99+
*!*
100+
let j = i;
101+
*/!*
102+
let shooter = function() { // shooter function
103+
alert( *!*j*/!* ); // should show its number
104+
};
105+
shooters.push(shooter);
106+
i++;
107+
}
108+
109+
return shooters;
110+
}
123111
124-
Now, as you've put so much effort into reading this, and the final recipe is so simple - just use `for`, you may wonder -- was it worth that?
112+
let army = makeArmy();
125113
126-
Well, if you could easily answer the question, you wouldn't read the solution. So, hopefully this task must have helped you to understand things a bit better.
114+
army[0](); // 0
115+
army[5](); // 5
116+
```
127117

128-
Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios, where such problems are real.
118+
Il ciclo `while`, come `for`, crea un nuovo Lexical Environment ad ogni esecuzone. Quindi siamo sicuri di ottener il giusto valore di `shooter`.
129119

120+
Copiamo `let j = i`. Questo rende il corpo del ciclo locale e copia su `j` il valore di `i`. Gli oggetti primitivi vengono copiati per valore, quindi ora abbiamo un copia indipendente di `i`, che appartiene all iterazione corrente.

1-js/06-advanced-functions/03-closure/10-make-army/task.md

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,34 @@ importance: 5
22

33
---
44

5-
# Army of functions
5+
# Funzione crea eserciti
66

7-
The following code creates an array of `shooters`.
7+
Il seguente codice crea un array di `shooters`.
88

9-
Every function is meant to output its number. But something is wrong...
9+
Ogni funzione è pensata per ritornare il numero, Ma qualcosa non va...
1010

1111
```js run
1212
function makeArmy() {
1313
let shooters = [];
1414

1515
let i = 0;
1616
while (i < 10) {
17-
let shooter = function() { // create a shooter function,
18-
alert( i ); // that should show its number
17+
let shooter = function() { // shooter function
18+
alert( i ); // should show its number
1919
};
20-
shooters.push(shooter); // and add it to the array
20+
shooters.push(shooter);
2121
i++;
2222
}
2323

24-
// ...and return the array of shooters
2524
return shooters;
2625
}
2726

2827
let army = makeArmy();
2928

30-
*!*
31-
// all shooters show 10 instead of their numbers 0, 1, 2, 3...
32-
army[0](); // 10 from the shooter number 0
33-
army[1](); // 10 from the shooter number 1
34-
army[2](); // 10 ...and so on.
35-
*/!*
29+
army[0](); // the shooter number 0 shows 10
30+
army[5](); // and number 5 also outputs 10...
31+
// ... all shooters show 10 instead of their 0, 1, 2, 3...
3632
```
3733

38-
Why do all of the shooters show the same value?
39-
40-
Fix the code so that they work as intended.
34+
Perché tutti gli eserciti possiedono lo stesso numero di militari? Modificate il codice in modo tale che funzioni correttamente.
4135

1-js/06-advanced-functions/03-closure/8-make-army/solution.md

Lines changed: 0 additions & 120 deletions
This file was deleted.

0 commit comments

Comments
 (0)