使用eval()的奇怪闭包行为 - 为什么?

mis*_*nky 4 javascript closures eval

首先,请不要警告我反对eval().我知道了.假设我只是好奇......

接下来,在以下代码中,eval(...)创建一个闭包并捕获参数"arg1".

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

    eval(fnStr);
}

test('hek');
Run Code Online (Sandbox Code Playgroud)

这个输出是"封闭打印arg1:hek".大!正如所料.

但是......如果我将eval分配给变量并执行相同的操作,则闭包不会捕获"arg1".

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

    fn_(fnStr);
}
test('hek'); 
Run Code Online (Sandbox Code Playgroud)

此代码段的输出是未定义arg1.如果我测试以确保eval和fn_相等,它们就是......

注意,如果我将this.arg2放在test()的主体中,则eval和fn_都会在闭包中捕获arg2.所以这种怪异似乎只适用于你要关闭的函数的参数.

  1. 为什么会这样?
  2. 如何使它工作?也就是说,我如何将eval函数赋值给变量并使用该变量来捕获参数?

Bar*_*mar 5

eval是由编译器特别识别的.这是允许它引入和访问局部变量绑定的原因.但编译器只能在其正常名称使用时识别它.当它看到一个调用时fn_,它不能告诉这个变量是等价的eval,所以它将它编译为普通的函数调用.

有关此的大量详细信息,请参阅

javascript eval被认为是疯了