You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/03-closure/10-make-army/solution.md
+51-51Lines changed: 51 additions & 51 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,89 +37,89 @@ Examinemos lo que sucede dentro de `makeArmy`, y la solución será obvia.
37
37
38
38
Si miramos la fuente:
39
39
40
-
```js
41
-
function makeArmy() {
42
-
...
43
-
let i = 0;
44
-
while (i < 10) {
45
-
let shooter = function() { // shooter function
40
+
```js
41
+
function makeArmy() {
42
+
...
43
+
let i = 0;
44
+
while (i < 10) {
45
+
let shooter = function() { // shooter function
46
46
alert( i ); // debería mostrar su número
47
-
};
47
+
};
48
48
shooters.push(shooter); // agrega la función al array
49
49
i++;
50
-
}
51
-
...
52
-
}
53
-
```
50
+
}
51
+
...
52
+
}
53
+
```
54
54
55
55
Podemos ver que todas las funciones `shooter` están creadas en el ambiente léxico asociado a la ejecución de `makeArmy()`. Pero cuando se llama a `army[5]()`, `makeArmy` ya ha terminado su trabajo, y el valor final de `i` es `10` (`while` finaliza en `i=10`).
56
56
57
57
Como resultado, todas las funciones `shooter` obtienen el mismo valor del mismo entorno léxico externo, que es el último valor `i=10`.
58
58
59
-

59
+

60
60
61
61
Como puedes ver arriba, con cada iteración del bloque `while {...}` un nuevo ambiente léxico es creado. Entonces, para corregir el problema podemos copiar el valor de `i` en una variable dentro del bloque `while {...}` como aquí:
62
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*/!* ); // debería mostrar su número
74
-
};
75
-
shooters.push(shooter);
76
-
i++;
77
-
}
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*/!* ); // debería mostrar su número
74
+
};
75
+
shooters.push(shooter);
76
+
i++;
77
+
}
78
78
79
-
return shooters;
80
-
}
79
+
return shooters;
80
+
}
81
81
82
-
let army = makeArmy();
82
+
let army = makeArmy();
83
83
84
84
// Ahora el código funciona correctamente
85
-
army[0](); // 0
86
-
army[5](); // 5
87
-
```
85
+
army[0](); // 0
86
+
army[5](); // 5
87
+
```
88
88
89
89
Aquí `let j = i` declara una variable de iteración local `j` y copia `i` en ella. Las primitivas son copiadas por valor, así que realmente obtenemos una copia independiente de `i`, perteneciente a la iteración del bucle actual.
90
90
91
91
Los shooters funcionan correctamente, porque el valor de `i` ahora vive más cerca. No en el ambiente léxico de `makeArmy()` sino en el que corresponde a la iteración del bucle actual:
92
92
93
-

93
+

94
94
95
95
Tal problema habría sido evitado si hubiéramos usado `for` desde el principio:
96
96
97
-
```js run demo
98
-
function makeArmy() {
97
+
```js run demo
98
+
function makeArmy() {
99
99
100
-
let shooters = [];
100
+
let shooters = [];
101
101
102
-
*!*
103
-
for(let i = 0; i < 10; i++) {
104
-
*/!*
105
-
let shooter = function() { // shooter function
102
+
*!*
103
+
for(let i = 0; i < 10; i++) {
104
+
*/!*
105
+
let shooter = function() { // shooter function
106
106
alert( i ); // debería mostrar su número
107
-
};
108
-
shooters.push(shooter);
109
-
}
107
+
};
108
+
shooters.push(shooter);
109
+
}
110
110
111
-
return shooters;
112
-
}
111
+
return shooters;
112
+
}
113
113
114
-
let army = makeArmy();
114
+
let army = makeArmy();
115
115
116
-
army[0](); // 0
117
-
army[5](); // 5
118
-
```
116
+
army[0](); // 0
117
+
army[5](); // 5
118
+
```
119
119
120
120
Esto es esencialmente lo mismo, ya que cada iteración de `for` genera un nuevo ambiente léxico con su propia variable `i`. Así el `shooter` generado en cada iteración hace referencia a su propio `i`, de esa misma iteración.
121
121
122
-

122
+

123
123
124
124
Ahora, como has puesto mucho esfuerzo leyendo esto, y la receta final es tan simple: simplemente usa `for`, puede que te preguntes: ¿valió la pena?
0 commit comments