2011-01-09 10 views
7

¿Hay alguna manera de romper un cierre fácilmente en JavaScript? El más cercano que he conseguido es la siguiente:Cómo romper los cierres en JavaScript

var src = 3; 
function foo() { 
    return function() { 
     return src; } 
    } 
function bar (func) { 
    var src = 9; 
    return eval('('+func.toString()+')')(); // This line 
} 
alert(bar(foo())); 

Este imprime '9', en lugar de '3', como cierre dictaría. Sin embargo, este enfoque parece algo feo para mí, ¿hay alguna forma mejor?

+5

¿Por qué alguna vez necesitarías hacer esto? O_o –

+0

¿Qué estás tratando de lograr? Lo que estás describiendo parece ser un tipo completamente equivocado de cosas que quieres hacer. –

+5

Gosh, estás golpeando literalmente la mejor parte de JavaScript con su peor parte ... Estoy llorando en este momento; _; -1 –

Respuesta

1

Como han dicho otros, esto no parece ser lo correcto. Debería explicar por qué quiere esto y qué quiere lograr.

De todos modos, un posible enfoque podría ser acceder a las propiedades de un objeto dentro de su función. Ejemplo:

var src = 3; 

function foo (context) { 
    context = context || window; // Fall back to the global namespace as default context 

    return function() { 
     return context.src; 
    } 
} 

function bar (func) { 
    var context = {src: 9}; 
    return func(context); 
} 

alert(bar(foo)); 
+0

Supongo que esto significa "No usar cierres", y usar objetos en su lugar. Que puede ser lo que tengo que hacer. Creo que podría intentar pasar una función de argumentos y luego usar una declaración con, tan fea como sería. –

+0

No significa "No usar cierres". Los cierres son geniales. Parece que todavía no has entendido para qué sirven, si el código de tu pregunta es un intento de resolver un problema real. – Jakob

+0

Sé lo que es el cierre, pero necesito compilar el código de un archivo y usarlo en otro lugar, mientras tengo acceso a variables privadas. –

1

Si desea acceder a una variable en un ámbito más amplio, simplemente no reutilice el nombre de la variable en un ámbito más estrecho.

Así se supone que funciona. Trabaja con él en lugar de tratar de luchar contra él.

8

Su código no está rompiendo el cierre, solo está tomando el código que conforma una función y evaluándolo en un contexto diferente (donde el identificador src tiene un valor diferente). No tiene nada que ver con el cierre que ha creado sobre el original src.

Es imposible inspeccionar los datos que se han capturado en un cierre. En cierto sentido, estos datos son aún más "privados" que los miembros privados en Java, C++, C#, etc., donde siempre se puede utilizar la reflexión o la magia del puntero para acceder a ellos de todos modos.

2

Esto podría ser útil si está intentando crear múltiples métodos similares en un bucle. Por ejemplo, si está creando un manejador de clics en un bucle que depende de una variable de bucle para hacer algo un poco diferente en cada manejador. (Eliminé el "eval" porque no es necesario y, en general, nunca debería usarse).

// Assign initial value 
var src = 3; 

// This is the regular js closure. Variables are saved by reference. So, changing the later will 
// change the internal value. 
var byref = function() { 
    return src; 
} 

// To "break" the closure or freeze the external value the external function is create and executed 
// immidiatly. It is used like a constructor function which freezes the value of "src". 
var byval = function(s) { 
    return function() { return s }; 
}(src); 

src = 9; 

alert("byref: " + byref()); // output: 9 
alert("byval: " + byval()); // output: 3 
0

Aquí está el código para ver si puede entender, cierres definidos dentro de un bucle.

var clicked = false; 
for(var i=0;i<temp.length;i++){ 
    (function(index){ 
    if(clicked) return false; 
    $(temp[index]).on('click',function(){ 
    if($(temp[index]).text()=="" && !$(".cell1").val()){ 
     $(this).text(player1Val); 
     $(".cell1").val(true); 
     console.log("first player clicked "); 
     clicked = true; 
     $(this).off(); 
     for(var j=0;j<temp.length;j++){ 
      $(temp[j]).off('click'); 
     } 
     return false; 
    } 
    else return false; 
    }); 
})(i); 
}