-1

两个函数对象:

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

具有相同的源代码“function(){return k;}”,但它是在全局环境中查找f1的函数,而是捕获本地.kf2k

是否可以判断f2是闭包?typeof因为两者都有"function"帮助,也无济于事......

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

4

3 回答 3

2

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

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

发生的情况是 f1 是在顶级范围内定义的,但 f2 是在立即调用的函数的内部范围内定义的,然后返回到顶级。闭包是让 f2 在其定义的范围应该被销毁后访问 k 的原因。可以说 f2 在 k 上有一个闭包。

简而言之,没有办法让您知道该函数是在什么范围内创建的。

于 2016-03-27T20:50:48.610 回答
1

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

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

可以看到,f1 ref 指向的函数和 f2 ref 指向的函数有不同的作用域链,虽然它们都返回 k,但 k 指向的不是同一个区域。这并不是说如果 f2 或 f1 是一个闭包,它们都是函数,它们都有自己的闭包,但是在这个例子中,它们不引用同一个闭包。

他们都返回k,当他们这样做时,他们将在他们的闭包内部(或多或少等于他们的作用域链)找到'k'。对于 f1,您在这段代码中没有给它一个 'k',所以它一直查找,直到全局,如果仍然没有一个 'k',则返回 undefined。对于f2,in的范围function(k){}是f2的“最低范围”,它找到了一个“k”,所以返回它。这就是区别。

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

我的英文不好,希望能帮到你。

于 2016-03-28T13:08:22.373 回答
0

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

根据 ECMA 标准,闭包的范围是无法以编程方式访问的。

话虽如此,我编写了一个概念验证代码,可以确定一个函数是否为闭包,并根据您的示例函数进行定制。不同类型的闭包需要更复杂的机制,但它可能会起作用:

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');
于 2016-03-28T07:43:35.877 回答