1
var foo = (function(){
  var x = "bar";
  return function(){
    console.log(x);
  };
})();

console.log(foo.toString()); // function() {console.log(x);}

(foo)(); // 'bar'
eval('(' + foo.toString()+')()')); // error: x is undefined

为什么 var 不x记录为"bar"in foo.toString()

foo具有与其 toString() 值不匹配的行为。foo总是打印“bar”,但看着foo.toString()不会告诉你这一点。

有关吗?如果决定不反编译一个函数来获取它的 toString() 值,为什么不包括依赖于外部函数作用域的对象的解析呢?

有没有办法使用旧的反编译方法来获取给定函数背后的实际代码?

4

2 回答 2

3

您正在执行匿名函数,因此返回值被分配给foo. 如果你使用

var foo = function(){
  var x = "bar";
  return function(){
    console.log(x);
  };
};

foo.toString()显示匿名函数
foo().toString()返回函数

您从1eval创建一个新函数,与[创建的匿名函数的]初始范围的范围没有任何关系,并执行该函数,因此它会产生一个相关的. 这没什么好奇怪的。foo.toString()fooReferenceErrorx

1 eval("function (){console.log(x);})()")

于 2013-02-25T08:07:03.457 回答
2

由于 javascript 是函数范围的,因此在转换为字符串时会丢失其范围信息。因此,从此字符串中新创建的函数与原始函数无关。

我有两种解决方法:

首先,而不是让 foo 成为 IIFE,你可以拥有它:

var foo = function(){
  var x = "bar";
  return function(){
    console.log(x);
  };
};

然后调用 eval('(' + foo.toString() + ')()()'),当你执行函数并向下传递时,范围就会被创建。

或者您可以保留 IIFE,当您调用 eval('(' + foo.toString() + ')') 时,使用 apply 或 call 方法调用它并将 x 放入上下文对象或作为参数传入。

于 2017-02-09T16:28:48.907 回答