Is there any way to break a closure easily in JavaScript? The closest I have gotten is this:
var src = 3;
function foo () {
return function () {
return src; }
}
function bar (func) {
var src = 9;
return eval('('+func.toString()+')')(); // This line
}
alert(bar(foo()));
This prints '9', instead of '3', as a closure would dictate. However, this approach seems kind of ugly to me, are there any better ways?
This could be useful if you are trying to create multiple similar methods in a loop. For example, if you're creating a click handler in a loop that relies on a loop variable to do something a little different in each handler. (I've removed the "eval" because it is unnecessary, and should generally never be used).
// 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
Your code is not breaking the closure, you're just taking the code the makes up a function and evaluating it in a different context (where the identifier src
has a different value). It has nothing at all to do with the closure that you've created over the original src
.
It is impossible to inspect data that has been captured in a closure. In a sense, such data are even more "private" than private members in Java, C++, C# etc where you can always use reflection or pointer magic to access them anyway.
As others said this doesn't seem to be the right thing to do. You should explain why you want this and what you want to achieve.
Anyway, one possible approach could be to access properties of an object inside your function. Example:
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));
If you want to access a variable in a wider scope, just don't reuse the variable name in a narrower scope.
That's how it is supposed to work. Work with it instead of trying to fight it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With