是否可以在Javascript中区分非捕获函数和闭包?

时间:2016-03-27 20:27:31

标签: javascript introspection lexical-closures

两个功能对象:

// toplevel
var f1 = function(){return k;};
var f2 = (function(k){return function(){return k;}})(42);

具有相同的源代码“function(){return k;}”但f1是在全局环境中查找k的函数,而f2则是<捕获本地k的强>关闭。

有可能告诉f2是封闭吗?两者的typeof"function",但没有帮助......

例如,将函数的源代码存储在数据库中可能有意义,因为您可以使用eval重建函数。由于捕获的变量,存储闭包的源代码不会起作用。

3 个答案:

答案 0 :(得分:2)

闭包不是类型。闭包是允许函数访问其范围内的变量的东西,即使在该范围应该消失之后也是如此。看看他不知道JS的书籍,以获得更详细的描述。

你提出的第二件事是立即调用的函数。函数周围的()使它成为一个表达式。它被评估并返回,然后立即被调用。

正在发生的事情是f1在顶级作用域中定义,但f2在紧接调用的函数的内部作用域中定义,然后返回到顶级。闭包是让f2在其定义的范围被销毁之后访问k的原因。可以说f2在k上有一个闭包。

简而言之,没有办法告诉你函数的创建范围。

答案 1 :(得分:1)

正如ncphillips所说,Closure不是js类型。它是一种数据结构设计,用于解决动态范围问题。您可以查看以下链接:https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope_vs._dynamic_scope 在大多数函数式编程语言中,闭包对开发人员是透明的,没有办法访问或控制这种结构。 每次vm创建一个闭包(通常在你声明一个函数时发生),它会查找作用域链并且链接到它们(这是我的话,也许不是很清楚)&#39 ;。在您的代码中:

var f1 = function(){return k;};
var f2 = (function(k){return function(){return k;}})(42);

你可以看到,f1引用的函数和函数f2引用具有不同范围链的函数,虽然它们都返回k,但k引用的是不是相同的区域。它不是说如果f2或f1是一个闭包,它们都是函数,它们都有它们的闭包,但在这个例子中,它们没有引用相同的闭包。

他们都返回k,当他们这样做时,他们会查看他们的封闭(或多或少等于他们的范围链)以找到&#39; k。对于f1,你没有给它一个&#39; k&#39;在这段代码中,所以它一直向上看,直到全局,如果还没有&#39; k&#39;然后返回undefined。对于f2,function(k){}中的范围是f2&#39;最低范围&#39;,它找到了&#39; k&#39;,所以返回它。这就是区别。

闭包创建的关键字是函数声明,当vm声明一个函数时,它给函数一个闭包,依赖于声明发生的范围。

我的英语并不好,只希望这可以帮到你。

答案 2 :(得分:0)

如果你在f1 / f2.prototype上查看Chrome调试器,你会得到一个可扩展的Object {}。在里面你有一个也可以扩展的构造函数。展开后,您可以在里面看到一个<function scope>项,其中包含k及其值。

根据ECMA标准,关闭的范围是inaccessible programatically

话虽这么说,我写了一个概念证明代码,可以确定一个函数是否是一个闭包,根据你的示例函数量身定制。不同类型的闭包需要更复杂的机制,但它可能有效:

var k=10;
var f1 = function(){return k;};
var f2 = (function(k){return function(){return k;}})(42);
function isClosure(f) {
    var testF=new Function('return ('+f.toString()+')();');
    return testF()!=f();
}

alert('f1 is '+(isClosure(f1)?'':'not')+' a closure\r\nf2 is '+(isClosure(f2)?'':'not')+' a closure');