Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to break closures in JavaScript

Tags:

javascript

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?

like image 483
Not a Name Avatar asked Jan 09 '11 20:01

Not a Name


4 Answers

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
like image 50
oneself Avatar answered Oct 25 '22 04:10

oneself


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.

like image 22
Jakob Avatar answered Oct 25 '22 05:10

Jakob


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));
like image 27
RoToRa Avatar answered Oct 25 '22 05:10

RoToRa


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.

like image 30
Quentin Avatar answered Oct 25 '22 04:10

Quentin