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吗?
答案 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不在全局范围内,但仍然可用于匿名内部函数。
您提出的方法可行,但需要在每次调用函数时分配数组。 (或者在全局范围内在函数外部分配。)