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

时间:2015-01-01 17:45:20

标签: javascript closures eval

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

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

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

    eval(fnStr);
}

test('hek');

这是"关闭打印arg1:hek"的输出。大!正如所料。

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

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

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

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

注意,如果我将this.arg2放在test()的主体中,则eval和fn_都会在闭包中捕获arg2。因此,这种奇怪现象似乎只适用于您要关闭的函数的参数。

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

1 个答案:

答案 0 :(得分:5)

eval由编译器特别识别。这是允许它引入和访问局部变量绑定的原因。但编译器只能在其正常名称使用时识别它。当它看到对fn_的调用时,它无法判断此变量是否等同于eval,因此它将其编译为正常的函数调用。

有关此内容的详情,请参阅

javascript eval considered crazy