4
votes

First, please no need to warn me against eval(). I get it. Assume I'm just curious...

Next, in the following code, eval(...) creates a closure and captures the argument "arg1".

var fnStr = "(function() { console.log('closure print arg1: '+arg1);})();";
function test(arg1) {

    eval(fnStr);
}

test('hek');

The output of this is "closure print arg1: hek". Great! As expected.

However ... if I assign eval to a variable and do the same thing, the closure doesn't capture "arg1".

var fn_ = eval;
var fnStr = "(function() { console.log('closure print arg1: '+arg1);})();";
function test(arg1) {

    fn_(fnStr);
}
test('hek'); 

The output from this snippet is that arg1 is not defined. If I test to ensure that eval and fn_ are equal, they are ...

NOTE that if I put a this.arg2 in the body of test(), both eval and fn_ capture arg2 in the closure. So this weirdness only appears to apply to the arguments of the function you're closing over.

  1. Why does this happen?
  2. How to make it work? That is, how can i assign the eval function to a variable and use that variable to also capture arguments?
1

1 Answers

5
votes

eval is recognized specially by the compiler. This is what allows it to introduce and access local variable bindings. But the compiler can only recognize it when it's used by its normal name. When it sees a call to fn_, it can't tell that this variable is equivalent to eval, so it compiles it as a normal function call.

For lots of details about this, see

javascript eval considered crazy