Variable scope by vplentinax · Pull Request #178 · javascript-tutorial/es.javascript.info
@@ -1,14 +1,15 @@
Let's examine what's done inside `makeArmy`, and the solution will become obvious. Examinemos lo que se hace dentro de `makeArmy`, y la solución será obvia.
1. It creates an empty array `shooters`: 1. Crea un array vacío. `shooters`:
```js let shooters = []; ``` 2. Fills it in the loop via `shooters.push(function...)`.
Every element is a function, so the resulting array looks like this: 2. Lo llena en el bucle a través de `shooters.push(function...)`.
Cada elemento es una función, por lo que el array resultante se ve así:
```js no-beautify shooters = [ Expand All @@ -24,38 +25,38 @@ Let's examine what's done inside `makeArmy`, and the solution will become obviou function () { alert(i); } ]; ```
3. El array se devuelve desde la función.
3. The array is returned from the function.
Then, later, the call to `army[5]()` will get the element `army[5]` from the array (it will be a function) and call it. Luego, más tarde, la llamada a `army[5] ()` obtendrá el elemento `army[5]` de el array (será una función) y lo llamará.
Now why all such functions show the same? Ahora, ¿por qué todas esas funciones muestran lo mismo?
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. Esto se debe a que no hay una variable local `i` dentro de las funciones `shooter`. Cuando se llama a tal función, toma `i` de su entorno léxico externo.
What will be the value of `i`? ¿Cuál será el valor de 'i'?
If we look at the source: Si miramos la fuente:
```js function makeArmy() { ... let i = 0; while (i < 10) { let shooter = function() { // shooter function alert( i ); // should show its number alert( i ); // debería mostrar su número }; ... } ... } ```
...We can see that it lives in the lexical environment associated with the current `makeArmy()` run. But when `army[5]()` is called, `makeArmy` has already finished its job, and `i` has the last value: `10` (the end of `while`). ... Podemos ver que vive en el entorno léxico asociado con la ejecución actual de `makeArmy()`. Pero cuando se llama a `army[5]()`, `makeArmy` ya ha terminado su trabajo, y `i` tiene el último valor: `10` (el final de `while`).
As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`. Como resultado, todas las funciones `shooter` obtienen del mismo entorno léxico externo, el último valor `i = 10`.
We can fix it by moving the variable definition into the loop: Podemos arreglarlo moviendo la definición de variable al bucle:
```js run demo function makeArmy() { Expand All @@ -66,7 +67,7 @@ function makeArmy() { for(let i = 0; i < 10; i++) { */!* let shooter = function() { // shooter function alert( i ); // should show its number alert( i ); // debería mostrar su número }; shooters.push(shooter); } Expand All @@ -80,15 +81,15 @@ army[0](); // 0 army[5](); // 5 ```
Now it works correctly, because every time the code block in `for (let i=0...) {...}` is executed, a new Lexical Environment is created for it, with the corresponding variable `i`. Ahora funciona correctamente, porque cada vez que se ejecuta el bloque de código en `for (let i = 0 ...) {...}`, se crea un nuevo entorno léxico para él, con la variable correspondiente `i`.
So, 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. That's why now it works. Entonces, el valor de `i` ahora vive un poco más cerca. No en el entorno léxico `makeArmy()`, sino en el entorno léxico que corresponde a la iteración del bucle actual. Por eso ahora funciona.

Here we rewrote `while` into `for`. Aquí reescribimos `while` en `for`.
Another trick could be possible, let's see it for better understanding of the subject: Podría usarse otro truco, veámoslo para comprender mejor el tema:
```js run function makeArmy() { Expand All @@ -100,7 +101,7 @@ function makeArmy() { let j = i; */!* let shooter = function() { // shooter function alert( *!*j*/!* ); // should show its number alert( *!*j*/!* ); // debería verse el núemero }; shooters.push(shooter); i++; Expand All @@ -115,6 +116,7 @@ army[0](); // 0 army[5](); // 5 ```
The `while` loop, just like `for`, makes a new Lexical Environment for each run. So here we make sure that it gets the right value for a `shooter`. El bucle `while`, al igual que `for`, crea un nuevo entorno léxico para cada ejecución. Así que aquí nos aseguramos de que obtenga el valor correcto para un `shooter`.
Copiamos `let j = i`. Esto hace que el cuerpo del bucle sea `j` local y copia el valor de `i` en él. Los primitivos se copian "por valor", por lo que en realidad obtenemos una copia independiente completa de `i`, que pertenece a la iteración del bucle actual.
We copy `let j = i`. This makes a loop body local `j` and copies the value of `i` to it. Primitives are copied "by value", so we actually get a complete independent copy of `i`, belonging to the current loop iteration.
Let's examine what's done inside `makeArmy`, and the solution will become obvious. Examinemos lo que se hace dentro de `makeArmy`, y la solución será obvia.
1. It creates an empty array `shooters`: 1. Crea un array vacío. `shooters`:
```js let shooters = []; ``` 2. Fills it in the loop via `shooters.push(function...)`.
Every element is a function, so the resulting array looks like this: 2. Lo llena en el bucle a través de `shooters.push(function...)`.
Cada elemento es una función, por lo que el array resultante se ve así:
```js no-beautify shooters = [ Expand All @@ -24,38 +25,38 @@ Let's examine what's done inside `makeArmy`, and the solution will become obviou function () { alert(i); } ]; ```
3. El array se devuelve desde la función.
3. The array is returned from the function.
Then, later, the call to `army[5]()` will get the element `army[5]` from the array (it will be a function) and call it. Luego, más tarde, la llamada a `army[5] ()` obtendrá el elemento `army[5]` de el array (será una función) y lo llamará.
Now why all such functions show the same? Ahora, ¿por qué todas esas funciones muestran lo mismo?
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. Esto se debe a que no hay una variable local `i` dentro de las funciones `shooter`. Cuando se llama a tal función, toma `i` de su entorno léxico externo.
What will be the value of `i`? ¿Cuál será el valor de 'i'?
If we look at the source: Si miramos la fuente:
```js function makeArmy() { ... let i = 0; while (i < 10) { let shooter = function() { // shooter function alert( i ); // should show its number alert( i ); // debería mostrar su número }; ... } ... } ```
...We can see that it lives in the lexical environment associated with the current `makeArmy()` run. But when `army[5]()` is called, `makeArmy` has already finished its job, and `i` has the last value: `10` (the end of `while`). ... Podemos ver que vive en el entorno léxico asociado con la ejecución actual de `makeArmy()`. Pero cuando se llama a `army[5]()`, `makeArmy` ya ha terminado su trabajo, y `i` tiene el último valor: `10` (el final de `while`).
As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`. Como resultado, todas las funciones `shooter` obtienen del mismo entorno léxico externo, el último valor `i = 10`.
We can fix it by moving the variable definition into the loop: Podemos arreglarlo moviendo la definición de variable al bucle:
```js run demo function makeArmy() { Expand All @@ -66,7 +67,7 @@ function makeArmy() { for(let i = 0; i < 10; i++) { */!* let shooter = function() { // shooter function alert( i ); // should show its number alert( i ); // debería mostrar su número }; shooters.push(shooter); } Expand All @@ -80,15 +81,15 @@ army[0](); // 0 army[5](); // 5 ```
Now it works correctly, because every time the code block in `for (let i=0...) {...}` is executed, a new Lexical Environment is created for it, with the corresponding variable `i`. Ahora funciona correctamente, porque cada vez que se ejecuta el bloque de código en `for (let i = 0 ...) {...}`, se crea un nuevo entorno léxico para él, con la variable correspondiente `i`.
So, 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. That's why now it works. Entonces, el valor de `i` ahora vive un poco más cerca. No en el entorno léxico `makeArmy()`, sino en el entorno léxico que corresponde a la iteración del bucle actual. Por eso ahora funciona.

Here we rewrote `while` into `for`. Aquí reescribimos `while` en `for`.
Another trick could be possible, let's see it for better understanding of the subject: Podría usarse otro truco, veámoslo para comprender mejor el tema:
```js run function makeArmy() { Expand All @@ -100,7 +101,7 @@ function makeArmy() { let j = i; */!* let shooter = function() { // shooter function alert( *!*j*/!* ); // should show its number alert( *!*j*/!* ); // debería verse el núemero }; shooters.push(shooter); i++; Expand All @@ -115,6 +116,7 @@ army[0](); // 0 army[5](); // 5 ```
The `while` loop, just like `for`, makes a new Lexical Environment for each run. So here we make sure that it gets the right value for a `shooter`. El bucle `while`, al igual que `for`, crea un nuevo entorno léxico para cada ejecución. Así que aquí nos aseguramos de que obtenga el valor correcto para un `shooter`.
Copiamos `let j = i`. Esto hace que el cuerpo del bucle sea `j` local y copia el valor de `i` en él. Los primitivos se copian "por valor", por lo que en realidad obtenemos una copia independiente completa de `i`, que pertenece a la iteración del bucle actual.
We copy `let j = i`. This makes a loop body local `j` and copies the value of `i` to it. Primitives are copied "by value", so we actually get a complete independent copy of `i`, belonging to the current loop iteration.