是否有可能以编程方式检测闭包?

时间:2013-11-21 01:02:08

标签: javascript closures

我有一个允许用户传递功能的功能。

function withPredicate(func){
    //...
}

在我的函数中,我需要检测用户传入的func是否有闭包。

获取函数名称并在窗口范围内搜索它是不够的。用户可能会传递匿名函数,而不会关闭,如:

var func = function(x){return x;};
withPredicate(func);

修改

我想我需要实现一个函数,它将函数作为参数并返回bool。

function hasClosure(func){
    //...
}

所以有几个测试用例:

hasClosure(function(x){return x;}); //return false

var something = 30;
var func1 = function(x){return x.age < something;} 
hasClosure(func1);   //return false

var Closure = function(){
    var something = 18;
    var itself = function(x){
        return x.age < something;
    };
    return itself;
};

var func2 = new Closure();
hasClosure(func2); //return true

最后一个返回true,因为func2不是顶级函数。当我在函数体中看到一些自由变量,如something时,它可以解析为其闭包中定义的变量而不是窗口中定义的变量。

实际上,我现在需要做的是根据传递给我的函数的func做一些操作。我可以使用JSLint来获取未声明的变量。但我还需要解决这些变量。我可以只在全局范围内解析变量。但我仍然需要一种方法来确保在全局范围内解析这些变量是正确的。所以我需要检测闭包。

是否可以在javascript中以编程方式执行此操作?

2 个答案:

答案 0 :(得分:0)

正确的答案在很大程度上取决于“闭包”在这种情况下的含义。问题中的函数不使用外部作用域中的变量,因此粗略地说,不为此函数创建闭包。但严格来说,会为任何函数创建闭包,并使用该函数绑定定义上下文。因此,无论您想要检测什么,都需要详细的规范。

但我可以假设这里的闭包意味着函数是否引用在外部作用域中声明的变量(就像https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures指定的那样)。可以使用其中一个静态分析库。例如,JSLint报告使用但未声明的变量。假设未声明的变量仅来自较高范围,则表示已创建闭包。

答案 1 :(得分:0)

好吧,这真的很hacky,除非你的linting或其他东西,否则可能不值得在实际写作中付出努力:)

基本上你要做的就是确定一个函数是否是一个闭包是调用func.toString(),它将为你提供函数的来源。然后,您可以使用某种解析器解析函数,该解析器确定函数func的所有变量。您还需要确定和跟踪这些变量的定义方式。在你的标准中,它是一个闭包的标准,它有一个在函数作用域之外和窗口作用域之外定义的变量(因此是闭包范围)。因此,如果你能找到在这两个范围之外定义的任何变量,我们就找到了一个闭包。

所以继承hasClosure()的伪代码,实现乐趣。

func hasClosure(func)
   source = func.toString(); //eg "function x(a) {return new Array(a)}"
   variables = parseJSForVariables(source)//finds a and Array
   for variable in variables:
      if(variable not in window)
          if(variable not defined in function)
              return true //we got a closure
  return false //not a closure