[英]Returning functions in javascript, understanding scope & closures
I was looking at Mozillas developer site on javascript closure and they had this example of code. 我正在关注javascript关闭的Mozillas开发者网站,他们有这个代码示例。
function makeAdder(x){
return function (y) {
console.log(y + " this is y")
console.log(x + " this is x")
return x + y;
}
}
var add10 = makeAdder(10);
console.log(add10(2)); // 12
Now i understand the X attribute being set but what i dont get is how the scope of the y is being affected. 现在我理解正在设置的X属性,但我没有得到的是y的范围如何受到影响。 I know its a return function but my brain went to mush trying to visualise how you could set ay when there was no ref to it.
我知道它有一个返回功能,但是当我没有参考时,我的大脑试图想象你如何设置它。 could someone explain?
有人能解释一下吗
makeAdder
returns a function to which you can pass the y
parameter. makeAdder
返回一个可以传递y
参数的函数。 It is set at the time of invocation, as opposed to x
which is set at the time of creation of the new function (at the time of the invocation of makeAdder
). 它是在调用时设置的,而不是在创建新函数时设置的
x
(在调用makeAdder
)。
For the case of this example, the output is equivalent to having written: 对于此示例的情况,输出相当于已写入:
function add10(y) {
return 10 + y;
}
console.log(add10(2)); // 12
Nothing new is going on here. 这里没有新的东西。 The sample code is mainly trying to illustrate that a closure is being created for
x
. 示例代码主要是试图说明正在为
x
创建一个闭包。
So makeAdder
, here, is aptly named: when you pass 10 to it, it gives you a function that will add 10 to everything you pass to that new function . 所以
makeAdder
在这里恰当地命名:当你向它传递10时,它会为你提供一个函数 ,它将为你传递给新函数的所有内容添加10。
var add10 = makeAdder(10);
var add20 = makeAdder(20);
console.log(add10(1) + add20(1)); // 32
Surely, for the purpose of adding, it might be easier to just have a function that accepts two parameters and adds them. 当然,为了添加,可能更容易只有一个接受两个参数并添加它们的函数。 But this is not a lesson in adding, it is a lesson in closures.
但这不是一个补充的教训,它是闭包的一个教训。
A real world scenario might be something like this: 现实世界的场景可能是这样的:
var buttons = document.getElementsByClassName('myButton');
for(var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
alert('You clicked button ' + i);
};
}
In the above code, i
will have iterated through the entire set before any of the buttons are clicked. 在上面的代码中,
i
将在点击任何按钮之前迭代整个集合。 Therefore, all buttons will alert whatever buttons.length
is. 因此, 所有按钮都会提醒任何
buttons.length
是。 Instead, you could do the following: 相反,您可以执行以下操作:
var makeAlert = function(x) {
return function() {
alert('You clicked button ' + x);
};
};
for(var i = 0; i < buttons.length; i++) {
buttons[i].onclick = makeAlert(i);
}
The difference here is that i
is not being used when the button is clicked (which will be after the entire iteration), but it is used during the iteration, at a time when i
will have a different value for each button. 这里的不同之处在于单击按钮时没有使用
i
(将在整个迭代之后),但是在迭代期间使用它,此时i
将为每个按钮设置不同的值。
Instead of creating a variable, makeAlert
, you will often see this type of code being written as an anonymous function, invoked immediately. 您不会创建变量
makeAlert
,而是经常会看到这种类型的代码被编写为匿名函数,并立即调用。 The code below is essentially equivalent to the code above: 下面的代码基本上等同于上面的代码:
for(var i = 0; i < buttons.length; i++) {
buttons[i].onclick = (function(x) {
return function() {
alert('You clicked button ' + x);
};
})(i);
}
What you're asking for is a function that does something for you: 你要求的是一个为你做点什么的功能:
function giveMeAFunctionThatBeeps(){
return function () {
alert('Beep!');
}
}
var beeper = giveMeAFunctionThatBeeps();
beeper(); // beeps!
The actual giveMeAFunctionThatbeeps is just a factory that gives you a function that does what you want. 实际的giveMeAFunctionThatbeeps只是一个工厂,它为您提供了一个能够满足您需求的功能。
In the example they have provided, you're doing the same thing as the beeper but you're also passing in a value: 在他们提供的示例中,您正在做与蜂鸣器相同的事情,但您也传递了一个值:
function giveMeAFunctionThatBeepsANumber(x){
return function () {
alert('Beep ' + x);
}
}
This returns a beeper (it's a factory remember), but the beeper alerts the value of x. 这会返回一个蜂鸣器(它是一个工厂记得),但蜂鸣器会提醒x的值。
However, this value is set when you first create the beeper: 但是,首次创建蜂鸣器时会设置此值:
var beeper = giveMeAFunctionThatBeeps(5);
beeper(); // beeps 5!
The beeper is stuck beeping the value 5 now, and we can't do anything about it. 蜂鸣器现在正在嘀咕着价值5,我们无法做任何事情。
The next example is if you want to create a beeper that beeps any number: 下一个示例是如果您要创建一个发出任何数字的蜂鸣声:
function giveMeAFunctionThatBeepsANumber(){
return function (x) {
alert('Beep ' + x);
}
}
var beeper = giveMeAFunctionThatBeeps();
beeper(6); // beeps 6!
beeper(7); // beeps 7!
As now we're asking the factory to give us a function we can plug a number into. 现在我们要求工厂给我们一个函数,我们可以插入一个数字。
Then lastly, the original example, is both of the above combined: 最后,最初的例子,是以上两者的组合:
function giveMeAFunctionThatBeepsANumber(x){
return function (y) {
alert('Beep ' + (x + y));
}
}
var beeper = giveMeAFunctionThatBeeps(2);
When we create the beeper, we're passing in 2. Remember as above, we can't change this afterwards! 当我们创建蜂鸣器时,我们正在传递2.记住,如上所述,我们之后无法改变它! It will always beep 2...
它会一直发出哔哔声......
...but because it's a factory (preconfigured with value 2) returning a function that takes a parameter, we can customise it when we run it: ...但是因为它是一个工厂(预先配置了值2)返回一个带参数的函数,我们可以在运行时自定义它:
beeper(6); // beeps 8! because x was set when we created it, and y is what we pass in.
Functions can be seen as special objects that contain executable code as well as properties. 函数可以看作包含可执行代码和属性的特殊对象。 Every function has a special [scope] property that represents the environment it was in when it was defined.
每个函数都有一个特殊的[scope]属性,表示定义它时所处的环境。 If a function is returned from another function then this reference to the old environment is closed over by the new function in a "closure".
如果从另一个函数返回一个函数,那么这个对旧环境的引用将由“闭包”中的新函数关闭。
so when you call var add10 = makeAdder(10)
what happens is that the returned function's x
has the value 10
which is bound to it's scope, and the call console.log(add10(2))
prints 12
. 所以当你调用
var add10 = makeAdder(10)
时,返回的函数的x
的值是10
,它绑定到它的作用域,并且调用console.log(add10(2))
打印12
。
Consider reading this article for visualizing what are closures. 考虑阅读此文章的可视化是什么倒闭。 A more detailed explanation of closure could be found here .
关于闭合的更详细解释可以在这里找到。
The function makeAdder
returns a function when it is called. makeAdder
函数在调用时返回一个函数。 This function that makeAdder
returns accepts one parameter; makeAdder
返回的这个函数接受一个参数; which is called y
. 这叫做
y
。
The variable y
exists only during the invocation of the function returned by the makeAdder
. 变量
y
仅在调用makeAdder
返回的函数期间存在。 It is created each time is is called, and is destroyed when the function returns. 每次调用时都会创建它,并在函数返回时被销毁。
The variable x
on the other hand is created when makeAdder
is called, and persists due to the closure created by the function makeAdder
returns. 另一方面,变量
x
是在调用makeAdder
时创建的,并且由于makeAdder
函数返回的闭包而持续存在。 It will be destroyed when no more references to the function returned exists. 当不再存在对返回函数的引用时,它将被销毁。
So add10 = makeAdder(10);
所以
add10 = makeAdder(10);
is actually returning this function: 实际上是返回此功能:
function(y) {
console.log(y + " this is y")
console.log("10" + " this is x")
return 10 + y;
}
Then add10(2)
is calling that function, replacing y with 2 everywhere: 然后
add10(2)
调用该函数,将y替换为2:
console.log("2" + " this is y")
console.log("10" + " this is x")
return 10 + 2;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.