evaluación inmediata de cierre de javascript [duplicado]
-
06-07-2019 - |
Pregunta
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, genere una función que imprima el valor actual de i. Es decir. 3 funciones que imprimen diferentes índices.
¿Alguna idea?
Solución
Cree una función anónima que acepte i
como parámetro y devuelva esa determinada función:
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]();
}
Otros consejos
Solo otro enfoque, usando curry :
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)));
};
};
Verifique el fragmento anterior que se ejecuta aquí .
var iterate = (function () {
var i, j = [];
for (i = 0; i < 3; i += 1) {
j.push(i);
alert(j[j.length - 1]);
}
}());
No necesita cierre para simplemente generar un valor. Sin embargo, su código debe estar contenido en una función para la contención orientada a objetos. No es necesario llamar a las funciones para ejecutarlas.
Puede colocar el cuerpo de su bucle 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 "i" variable dentro del cuerpo del bucle que esencialmente oculta la `` i '' externa. El cierre que inserta 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 bucle. 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 " se le asigna 0, luego 1, luego 2 porque el bucle llama inmediatamente a la función.
función (i) {alerta (i)