有人能解释一下这个 JavaScript 自动执行函数吗?
var foo = (function(){
var x = 0;
return function(){return x++;};
})()
为什么 var x = 0 表达式只运行一次是我对此最大的误解。
var foo = (function(){
var x = 0;
return function(){return x++;};
})()
Why the var x = 0 expression only runs once is my biggest misunderstanding about this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
匿名函数立即被后面的
()
调用(不传入任何参数)。该函数在执行时返回另一个函数,该函数有自己的 x 变量,该变量在运行时会递增。因此,第一次运行时,
foo()
将为0
,第二次运行为1
,依此类推,因为x
它是随着不断增加而创建的。The anonymous function gets invoked immediately by the
()
that follows it (passing in no parameters). That function when executed is returning another function, which has it's ownx
variable that gets incremented when run.So
foo()
is going to be0
the first run,1
the second, etc, since thatx
it was created with continues to increment.实际上,在本例中,
x
是分配给foo
对象的块/闭包中的局部变量。当您调用 foo() 时,该值会递增。查看实际情况 - http://jsfiddle.net/3X283/
Actually in this case
x
is a local variable within the block/closure assigned to thefoo
object. One that gets incremented when you callfoo()
.Check it out in action - http://jsfiddle.net/3X283/
这就是所谓的 闭包 这里定义了两个函数 - 内部函数(这是闭包)和创建并返回闭包的外部。
您的代码立即调用外部函数并将结果(闭包)分配给
foo
。请注意,闭包内的代码不包含语句
var x = 0;
,因此当您调用foo()
时,它仅执行内部的代码闭包 (return x++;
)这里提到的
x
是在调用中实例化的。闭包的有趣之处在于,这个 x 在外部函数的调用之间是不同的 - 考虑下面的示例。 foo 和 bar 将彼此独立地递增,因为它们引用不同x
sThis is what is called a closure theere are two functions defined - the inner one (which is the closure) and the outer one which creates and returns the closure.
Your code calls the outer function immediately and assigns the result (the closure) to
foo
.Note the code inside the closure does not include the statement
var x = 0;
thus when you callfoo()
it only executes the code inside the closure (return x++;
)The
x
referred to in here is the one instantiated in the call. What makes closures interesting is that this x is different between invocations of the outer function - consider the example below. foo and bar will increment independantly of one another because they reference differentx
s您的代码:
相当于此代码:
很容易看出,当您像这样分解它时,函数
f()
仅被调用一次。它定义了x
,然后返回一个在f
的本地范围内定义的新函数。这个新函数通常被称为“匿名函数”(意味着它没有名称)或“闭包”。事实上,JavaScript 中的所有函数都是“闭包”——无论它们是否被命名。术语“闭包”仅意味着该函数保留对父函数作用域中定义的变量的访问权——即使在父函数退出后也是如此。现在,
foo
包含从f
返回的新函数(闭包)。您可以根据需要多次调用foo()
—— 每次调用时,x
都会被返回并进行后递增。由于 x 存在于闭包的父作用域中,因此它的值将在对闭包的多次调用中保持不变。更重要的是...一旦
f()
退出,其他代码现在就无法访问x
——这基本上意味着x
现在是“私人数据”的关闭。很整洁吧?Your code:
is equivalent to this code:
It's easy to see, when you break it up like this, that the function
f()
is only called once. It definesx
, and then returns a new function that is defined inside the local scope off
. This new function is often called an "anonymous function" (meaning that it has no name) or a "closure". In truth, all functions in javascript are "closures" -- whether or not they are named. The term "closure" simply means that the function retains access to the variables that were defined in the parent function's scope -- even after the parent function has exited.So now,
foo
contains the new function (the closure) that was returned fromf
. You can callfoo()
as many times as you like -- and each time you do,x
will be returned and post-incremented. Sincex
exists in the closure's parent scope, its value will persist across multiple calls to the closure.What's more... no other code now has access to
x
oncef()
has exited -- this basically means thatx
is now the "private data" of the closure. Pretty neat huh?变量
foo
被分配给自执行函数的结果,如下所示:声明一个名为
x
的变量,初始化为0
。返回一个函数,调用该函数时,将增加
x
的值。所以此时,
foo
引用了一个函数。调用它的方式是:
第一次调用它时,返回的值将是
0
,然后是1
、2
...嗯,等一下...,不应该是
1
、2
、3
...?你的方向是正确的,但在这种情况下,这不的原因是因为预增量之间的差异和后增量。 (
++var
与var++
)。不同之处在于,前增量的结果是变量增量后的值,而后增量的结果是变量之前的值 em> 增量。此示例说明了闭包的概念,这本质上意味着内部函数可以访问其周围函数中定义的变量。
The variable
foo
is being assigned to the result of the self-executing function, which goes as follows:Declares a variable named
x
initialized to0
.Returns a function that, when invoked, will increment the value of
x
.So at this point,
foo
references a function.The way you would invoke this is:
The first time this is invoked, the value returned will be
0
, then1
,2
...Well, wait a minute..., shouldn't it be
1
,2
,3
...?You are on the right track, but the reason why in this case this isn't true is because of the difference between pre-increment and post-increment. (
++var
vsvar++
). The difference is that the result of a pre-increment is the variable's value after increment, while the result of a post-increment is the variable's value before increment.This example illustrates the concept of closures, which essentially means that inner functions have access to the variables defined in their surrounding functions.
让我们分解一下...首先我们定义一个匿名函数:
然后立即执行它:
执行的结果是另一个函数:
并且当我们创建上述函数时,x=0 被闭包捕获。然后我们将这个结果函数分配给 foo:
以及闭包捕获的 x 值。每当执行 foo 时,x 就会递增。
Let's break it down... First we define an anonymous function:
We then immediately execute it:
The result of this execution is another function:
And the x=0 is captured by the closure when we created the above function. We then assign this resulting function to foo:
With the value of x captured by the closure. Whenever foo is executed, x is incremented.