una - tipos de scope javascript
javascript closure immediate evaluation (5)
Esta pregunta ya tiene una respuesta aquí:
Considere el siguiente código Javascript:
var a = [];
var f = function() {
for (var i = 0; i < 3; i++) {
a.push(function(){alert(i)});
}
for (var j = 0; j < 3; j++) {
a[j]();
}
};
Las alertas imprimen ''3'' las tres veces. Quiero un comportamiento diferente: en cada iteración del ciclo, se genera una función que imprime el valor actual de i. Es decir, 3 funciones que imprimen diferentes índices.
¿Algunas ideas?
Crea una función anónima que acepta i
como parámetro y devuelve esa función determinada:
for (var i = 0; i < 3; i++) {
a.push((function(i) {
return function() {
alert(i);
}
})(i));
}
for (var j = 0; j < 3; j++) {
a[j]();
}
O haga algo similar: cree una función anónima que acepte i
como parámetro para agregar la función a la matriz:
for (var i = 0; i < 3; i++) {
(function(i) {
a.push(function() {
alert(i);
});
})(i);
}
for (var j = 0; j < 3; j++) {
a[j]();
}
Puedes poner el cuerpo de tu loop en una función anónima:
var a = [];
for(var i = 0; i < 3; i++) (function(i) {
a.push(function() { alert(i); });
})(i)
for(var j = 0; j < 3; j++) {
a[j]();
}
Al crear esa función y pasar el valor del bucle de "i" como argumento, estamos creando una nueva variable "i" dentro del cuerpo del bucle que esencialmente oculta la "i" exterior. El cierre que presione en la matriz ahora ve la nueva variable, cuyo valor se establece cuando se llama a la función de función externa en el primer ciclo. Esto podría ser más claro si usamos un nombre diferente cuando creamos la nueva variable ... Esto hace lo mismo:
var a = [];
for(var i = 0; i < 3; i++) (function(iNew) {
a.push(function() { alert(iNew); });
})(i)
for(var j = 0; j < 3; j++) {
a[j]();
}
El valor de "iNew" tiene asignado 0, luego 1, luego 2 porque el ciclo llama inmediatamente a la función.
Solo otro enfoque, usando currying :
var a = [];
var f = function() {
for (var i = 0; i < 3; i++) {
a.push((function(a){alert(a);}).curry(i));
}
for (var j = 0; j < 3; j++) {
a[j]();
}
};
// curry implementation
Function.prototype.curry = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
Compruebe el fragmento de arriba que se ejecuta aquí .
función (i) {alerta (i)
var iterate = (function () {
var i, j = [];
for (i = 0; i < 3; i += 1) {
j.push(i);
alert(j[j.length - 1]);
}
}());
No es necesario cerrar para simplemente generar un valor. Sin embargo, su código debe estar contenido en una función para la contención orientada a objetos. Las funciones no tienen que ser llamadas para ser ejecutadas.