Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c48c52c

Browse files
authored
Merge pull request #2127 from MuhammedZakir/master
Improve make-army task
2 parents 894e1b5 + fdf8eb3 commit c48c52c

File tree

1 file changed

+96
-97
lines changed
  • 1-js/06-advanced-functions/03-closure/10-make-army

1 file changed

+96
-97
lines changed

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

Lines changed: 96 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
66
```js
77
let shooters = [];
88
```
9-
2. Fills it in the loop via `shooters.push(function...)`.
9+
2. Fills it with functions via `shooters.push(function)`in the loop.
1010

1111
Every element is a function, so the resulting array looks like this:
1212

@@ -26,105 +26,104 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
2626
```
2727

2828
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 (that's a function) and call 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-
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-
...
49-
}
50-
...
51-
}
52-
```
53-
54-
We can see that all `shooter` functions are created in the lexical environment, associated with the one `makeArmy()` run. But when `army[5]()` is called, `makeArmy` has already finished its job, and the final value of `i` is `10`(`while` finishes at `10`).
55-
56-
As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`.
57-
58-
![](lexenv-makearmy-empty.svg)
59-
60-
As you can see above, on each iteration of a `while {...} ` block, a new lexical environment is created.
61-
62-
So, to fix a problem we can copy the value of `i` into a variable within the `while {...}` block, like this:
63-
64-
```js run
65-
function makeArmy() {
66-
let shooters = [];
67-
68-
let i = 0;
69-
while (i < 10) {
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+
70102
*!*
71-
let j = i;
103+
for(let i = 0; i <10; i++) {
72104
*/!*
73-
let shooter = function() { // shooter function
74-
alert( *!*j*/!* ); // should show its number
75-
};
76-
shooters.push(shooter);
77-
i++;
78-
}
79-
80-
return shooters;
81-
}
82-
83-
let army = makeArmy();
84-
85-
// Now the code works correctly
86-
army[0](); // 0
87-
army[5](); // 5
88-
```
89-
90-
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.
91-
92-
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:
93-
94-
![](lexenv-makearmy-while-fixed.svg)
95-
96-
Such problem could also be avoided if we used `for` in the beginning, like this:
97-
98-
```js run demo
99-
function makeArmy() {
100-
101-
let shooters = [];
102-
103-
*!*
104-
for(let i = 0; i < 10; i++) {
105-
*/!*
106-
let shooter = function() { // shooter function
107-
alert( i ); // should show its number
108-
};
109-
shooters.push(shooter);
110-
}
111-
112-
return shooters;
113-
}
114-
115-
let army = makeArmy();
116-
117-
army[0](); // 0
118-
army[5](); // 5
119-
```
120-
121-
That's essentially, the same, as `for` on each iteration generates the new lexical environment, with its own variable `i`. So `shooter` generated in every iteration references its own `i`, from that very iteration.
122-
123-
![](lexenv-makearmy-for-fixed.svg)
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)
124123
125-
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?
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?
126125
127-
Well, if you could easily answer the question of that task, you wouldn't read the solution, so hopefully this task must have helped you to understand things a bit better.
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.
128127
129-
Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios where such problems are real.
128+
Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios, where such problems are real.
130129

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /