Function.toString()不尊重闭包范围

时间:2013-02-25 06:36:42

标签: javascript node.js

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"中记录为foo.toString()

foo的行为与其toString()值不匹配。 foo始终打印“bar”,但查看foo.toString()不会告诉您这一点。

它与this有关吗?如果决定不对函数进行反编译以获取其toString()值,为什么不包括依赖于外部函数范围的对象的解析?

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

2 个答案:

答案 0 :(得分:2)

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

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

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

您的evalfoo.toString() 1 创建新功能,与初始范围的范围无任何关联 [创建foo]的匿名函数,并执行该函数,因此会产生ReferenceError x。这没什么奇怪的。

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

答案 1 :(得分: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放在上下文对象中或作为参数传入。