我不明白这个闭包的例子

时间:2011-05-14 16:52:41

标签: javascript

Crockford有这个例子来保持myArray不在全球范围内:

var myName = (function() {
    var myArray = ['zero','one','two','three','four'];
    return function(X) {
        return myArray[X];
    }
}()); // This function is invoked immediately

result = myName(3); // Now invoke it "for real"
问:我不明白为什么不是

var myName = (function(X) {

问:当我调用myName(3)时,第二次执行“var myArray =”是不是? 假设它没有第二次执行,因为JavaScript知道它已经被定义了...... var stmt和return函数stmt之间的循环或其他逻辑怎么样?不是每次都会被执行吗?

问:您可以命名子功能并调用它而不是调用myName吗?

9 个答案:

答案 0 :(得分:5)

好吧,让我们打破这个......

var myName = (function(){
    ...
}());

该部分将myName设置为匿名函数返回的任何内容,如果是:

var myName = (function(){ return 42; }());

myName等于42。如果这没有意义,那就是同样的事情:

function someFunction(){ return 42; }
var myName = someFunction();

因此,在您的示例中,myName设置为function(X){ return myArray[X] }。所以myName 一个函数。当您调用它时,唯一运行的代码是return myArray[x]myArray保留在所谓的闭包中,它仅暴露给myName函数及其周围的匿名函数。

我几年前写了一篇关于闭包的文章可能对你有所帮助:http://www.htmlgoodies.com/primers/jsp/article.php/3606701/Javascript-Basics-Part-9.htm(向下滚动到“闭包”标题)。

答案 1 :(得分:3)

好的,这就是.. 回答Q1。它不是myName =(function(x),因为括号内的部分返回一个带X的函数。即myname未赋值给(function(){}),而是返回它的返回值。

Q2。否则,当你第二次调用myName时它已经指向内部函数,因此根本不会调用外部函数。(这是闭包的特殊性,即使外部函数完成,值也会在内部函数中保持活动状态。)

Q3。好吧,我们可以命名内部函数,但名称只在外部函数内有效,因为外部函数已经完成,名称将无用。

答案 2 :(得分:1)

外部函数不必具有参数X,因为它的唯一目的是返回另一个函数(然后进行参数化)。因此,这里不需要争论。

因此唯一的影响是将function(X)...事物绑定到变量myName。因此,没有其他类似循环的结构在这里有意义。

答案 3 :(得分:1)

Q1 + 2:注意注释的“{1}}权限”“立即调用此函数”。定义的外部函数不存储在()中,而是立即调用。然后它自己返回一个匿名函数,该函数没有名称,只需要一个参数(myName)。返回的此函数存储在myName中。

要掌握闭包,你应该开始考虑函数,就像变量的另一个值一样,可以存储并返回jsut作为任何其他值。

问题3:myName 子功能。

答案 4 :(得分:1)

依次回答:

首先,为什么它是var myName = (function() {而不是var myName = (function(x) {

在这种情况下,因为创建要返回的函数不需要x值。返回函数中包含的数组的数据结构是硬编码的,因此您不需要其他信息来构造它。

的方式大致相同
function a() { 
  return 1 + 2;
}

没有任何参数,因为它的值是硬编码的。这是函数作为数据或first class functions

的示例

问题二:每次都执行var myArray

缺点是没有。此时已分配myArray,因此它具有系统已计算的值。在这种情况下,它是一个功能。 myArray药水已经设定,所以没有理由继续执行它。如果外部函数没有返回一个新函数,那么它需要一次又一次地调用,但这会破坏这种抽象的目的。

问题三:你可以调用内部函数吗?

不,它超出了范围。这个例子的重点是你已经定义了一个函数发生器。

答案 5 :(得分:1)

回答第一个问题: 不,第一个“行”返回一个函数,所以当你调用“myName”时,你实际上是在执行返回的函数

function(X) {
        return myArray[X];
}

回答第二个问题

不,这样的函数仍然可以引用数组“myArray”...实际上这个闭包的目的是让myArray在全局范围内可用

答案 6 :(得分:1)

用语言说:

myName是立即执行的匿名函数的结果。它返回一个函数引用(到一个匿名函数)。该函数有一个参数:X。执行最顶层的匿名函数后,myName是对内部匿名函数的引用。

现在内部匿名函数可以通过闭包(myArray访问myArray,并且返回的匿名函数都存在于最顶层匿名函数的范围内)。因此,如果执行myName,则实际执行内部匿名函数,该函数可以访问myArray

最顶层的匿名函数立即执行一次(它返回对内部函数的引用)。因此myArray在该执行上下文中声明,并且只发布一次。

答案 7 :(得分:1)

由于myName对象(函数)的定义以'()'结尾,因此立即调用其函数,返回一个新函数,该函数将myArray变量静态绑定到它。然后myName可以全局访问,但myArray不是在函数闭包中。当您引用myName()时,它具有对绑定数组的独占访问权。

答案 8 :(得分:0)

这种方法确保myArray仅在外部函数'立即调用'时分配一次。在调用它之后,myArray不在全局范围内,但仍然可用于匿名内部函数。

您提出的方法可行,但需要在每次调用函数时分配数组。 (或者在全局范围内在函数外部分配。)