请解释 JavaScript 闭包在循环中的使用 [英] Please explain the use of JavaScript closures in loops
问题描述
我已经阅读了许多关于闭包和循环内闭包的解释.我很难理解这个概念.我有这个代码:有没有办法尽可能地减少代码,这样闭包的概念就可以更清楚了.我很难理解 i
位于两个括号内的部分.谢谢
I have read a number of explanations about closures and closures inside loops. I have a hard time understanding the concept. I have this code: Is there a way to reduce the code as much as possible so the concept of closure can be made clearer. I am having a hard time understanding the part in which the i
is inside two parenthesis. Thanks
function addLinks () {
for (var i=0, link; i<5; i++) {
link = document.createElement("a");
link.innerHTML = "Link " + i;
link.onclick = function (num) {
return function () {
alert(num);
};
}(i);
document.body.appendChild(link);
}
}
window.onload = addLinks;
推荐答案
WARNING: Long(ish) Answer
这是直接从我在公司内部维基上写的一篇文章中复制的:
问题:如何在循环中正确使用闭包?快速回答:使用函数工厂.
Question: How to properly use closures in loops? Quick answer: Use a function factory.
for (var i=0; i<10; i++) {
document.getElementById(i).onclick = (function(x){
return function(){
alert(x);
}
})(i);
}
或更容易阅读的版本:
function generateMyHandler (x) {
return function(){
alert(x);
}
}
for (var i=0; i<10; i++) {
document.getElementById(i).onclick = generateMyHandler(i);
}
这常常让不熟悉 JavaScript 或函数式编程的人感到困惑.这是对闭包是什么误解的结果.
This often confuse people who are new to javascript or functional programming. It is a result of misunderstanding what closures are.
闭包不仅仅是传递变量的值,甚至是对变量的引用.闭包捕获变量本身!以下代码说明了这一点:
A closure does not merely pass the value of a variable or even a reference to the variable. A closure captures the variable itself! The following bit of code illustrates this:
var message = 'Hello!';
document.getElementById('foo').onclick = function(){alert(message)};
message = 'Goodbye!';
单击元素foo"将生成一个带有消息的警告框:再见!".因此,在循环中使用一个简单的闭包将导致所有闭包共享相同的变量,并且该变量将包含循环中分配给它的最后一个值.例如:
Clicking the element 'foo' will generate an alert box with the message: "Goodbye!". Because of this, using a simple closure in a loop will end up with all closures sharing the same variable and that variable will contain the last value assigned to it in the loop. For example:
for (var i=0; i<10; i++) {
document.getElementById('something'+i).onclick = function(){alert(i)};
}
所有元素在点击时都会生成一个数字为 10 的警报框.事实上,如果我们现在执行 i="hello";
现在所有元素都会生成一个hello"警报!变量 i 在十个函数加上当前函数/范围/上下文中共享.把它想象成一种只有相关函数才能看到的私有全局变量.
All elements when clicked will generate an alert box with the number 10. In fact, if we now do i="hello";
all elements will now generate a "hello" alert! The variable i is shared across ten functions PLUS the current function/scope/context. Think of it as a sort of private global variable that only the functions involved can see.
我们想要的是该变量的一个实例,或者至少是对变量的简单引用,而不是变量本身.幸运的是,javascript 已经有一种传递引用(对于对象)或值(对于字符串和数字)的机制:函数参数!
What we want is an instance of that variable or at least a simple reference to the variable instead of the variable itself. Fortunately javascript already has a mechanism for passing a reference (for objects) or value (for strings and numbers): function arguments!
当在javascript中调用一个函数时,如果它是一个对象,则该函数的参数通过引用传递,如果它是一个字符串或数字,则通过值传递.这足以打破闭包中的变量共享.
When a function is called in javascript the arguments to that function is passed by reference if it is an object or by value if it is a string or number. This is enough to break variable sharing in closures.
所以:
for (var i=0; i<10; i++) {
document.getElementById(i).onclick =
(function(x){ /* we use this function expression simply as a factory
to return the function we really want to use: */
/* we want to return a function reference
so we write a function expression*/
return function(){
alert(x); /* x here refers to the argument of the factory function
captured by the 'inner' closure */
}
/* The brace operators (..) evaluates an expression, in this case this
function expression which yields a function reference. */
})(i) /* The function reference generated is then immediately called()
where the variable i is passed */
}
这篇关于请解释 JavaScript 闭包在循环中的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!