Cierre de Javascript?

Método 1

function transform(ar) { var alStr = []; for(var i=0; i<ar.length; i++) { alStr[i] = (function(v) { return (function() { return v; }); }(ar[i])); } return alStr; } var a = ["a", 24, { foo: "bar" }]; var b = transform(a); a[1]; b[1](); 

Método # 2

 function transform(ar) { var alStr = []; for(var a in ar) { var O = function() { return a; } alStr.push(O); } return alStr; } var a = ["a", 24, { foo: "bar" }]; var b = transform(a); a[1]; b[1](); 

Los métodos mencionados anteriormente se utilizan para convertir los objetos de una matriz en funciones individuales que, al ejecutarse, devuelven el objeto de la matriz específica. ¿Quieres saber por qué el método # 1 funciona y el método # 2 no?

En el Método # 2 hay dos problemas:

  1. Está devolviendo el nombre de clave, a , en lugar del valor de matriz, ar[a] . Es decir, en lugar de return a; quieres return ar[a]; .

  2. La función siempre se referirá al último valor en bucle porque hace referencia al mismo objeto de scope. Para crear un nuevo objeto de scope, necesitará un cierre, un bloque with o una función enlazada.

Con un cierre:

 for(var a in ar) { var O = (function(val) { return function() { return val; } })(ar[a]); alStr.push(O); } 

Con un bloque with :

 for(var a in ar) { with({val: ar[a]}) { alStr.push(function() { return val; }); } } 

Con una función encuadernada:

 for(var a in ar) { var O = function(x) { return x; }; alStr.push(O.bind(null, arr[a])); } 

Peter Olson tiene razón. Sin embargo, la forma más moderna (¿correcta?) De hacer esto es usar function.bind(obj, val) . Introducido un poco recientemente, function.bind permite pasar variables por valor y en ciertos contextos. Lea más aquí .

Entonces, podrías escribir algo como esto:

 function transform(ar) { var alStr = []; var O = function(x) { return x } for(var a in ar) { alStr.push(O.bind(null, ar[a])); } return alStr; } var a = ["a", 24, 12345]; var b = transform(a); console.log(a[2]); b[2](); 

Este es un paradigma más correcto debido al hecho de que iniciar cierres tiene implicaciones muy claras. Sin embargo, el uso de vinculación tiende a ser un enfoque funcional que se utiliza específicamente cuando se llama a una función (en contextos particulares o con estipulaciones particulares).

Usar un bloque with también tiene algunas desventajas (hay muchas preguntas al respecto).

Bono : si quería que b también representara los cambios posteriores en a matriz, esta solución resuelve ese problema:

 function transform(ar) { var alStr = []; var O = function(x) { return ar[x] } for(var a in ar) { alStr.push(O.bind(null, a)); } return alStr; } var a = ["a", 24, 12345]; var b = transform(a); console.log(a[2]); console.log(b[2]()); console.log("*********"); a[2] = "new value!"; console.log(a[2]); console.log(b[2]());