Merge pull request #2127 from MuhammedZakir/master

Improve make-army task
This commit is contained in:
Ilya Kantor 2020-09-23 12:22:20 +03:00 committed by GitHub
commit c48c52cb81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6,7 +6,7 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
```js ```js
let shooters = []; let shooters = [];
``` ```
2. Fills it in the loop via `shooters.push(function...)`. 2. Fills it with functions via `shooters.push(function)` in the loop.
Every element is a function, so the resulting array looks like this: Every element is a function, so the resulting array looks like this:
@ -27,13 +27,13 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
3. The array is returned from the function. 3. The array is returned from the function.
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. 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.
Now why do all such functions show the same value, `10`? Now why do all such functions show the same value, `10`?
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. 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.
What will be the value of `i`? Then, what will be the value of `i`?
If we look at the source: If we look at the source:
@ -45,21 +45,20 @@ function makeArmy() {
let shooter = function() { // shooter function let shooter = function() { // shooter function
alert( i ); // should show its number alert( i ); // should show its number
}; };
... shooters.push(shooter); // add function to the array
i++;
} }
... ...
} }
``` ```
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`). 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`).
As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`. As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`.
![](lexenv-makearmy-empty.svg) ![](lexenv-makearmy-empty.svg)
As you can see above, on each iteration of a `while {...} ` block, a new lexical environment is created. 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:
So, to fix a problem we can copy the value of `i` into a variable within the `while {...}` block, like this:
```js run ```js run
function makeArmy() { function makeArmy() {
@ -118,13 +117,13 @@ army[0](); // 0
army[5](); // 5 army[5](); // 5
``` ```
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. 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.
![](lexenv-makearmy-for-fixed.svg) ![](lexenv-makearmy-for-fixed.svg)
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? 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?
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. 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.
Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios where such problems are real. Besides, there are indeed cases when one prefers `while` to `for`, and other scenarios, where such problems are real.