Article originated from http://www.cnblogs.com/snandy/archive/2011/03/01/1967628.html
A netizen asked a question, such as the next HTML, why click All the paragraph p output is 5, rather than alert out the corresponding 0,1,2,3,4.
123456789101112131415161718192021222324252627 |
<!DOCTYPE HTML>
<meta charset=
"utf-8"
/>
<title>闭包演示</title>
<style type=
"text/css"
>
p {background:gold;}
</style>
<script type=
"text/javascript"
>
function
init() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
pAry[i].onclick =
function
() {
alert(i);
}
}
}
</script>
<body onload=
"init();"
>
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
|
The above scenes are often encountered by beginners. That is, the collection of HTML elements that loop to add events to the element. The corresponding index is obtained in the event response function (handler). But each fetch is the index of the last loop.
The reason is that beginners do not understand the characteristics of JavaScript closures. Through Element.onclick=function () {alert (i);} method to add a click event to an element. Response functions function () {alert (i);} I is not the corresponding I (such as 0,1,2,3,4) in each cycle, but the value of the last I after the loop is 5. In other words, the response function in the loop is not able to save the corresponding value I, but the last i++ value of 5.
Understand the reasons and find out a lot of solutions (purely interest). First two to think of
1. Save the variable i to each paragraph object (p)
123456789 |
function
init1() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
pAry[i].i = i;
pAry[i].onclick =
function
() {
alert(
this
.i);
}
}
}
|
2. Save the variable i in the anonymous function itself
12345678 |
function
init2() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
(pAry[i].onclick =
function
() {
alert(arguments.callee.i);
}).i = i;
}
}
|
And then I thought about three kinds of
3, add a layer of closure, I in the form of function parameters passed to the inner layer function
12345678910 |
function
init3() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
(
function
(arg){
pAry[i].onclick =
function
() {
alert(arg);
};
})(i);
//调用时参数
}
}
|
4, add a layer of closure, I in the form of local variables passed to the inner layer function
1234567891011 |
function
init4() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
(
function
() {
var
temp = i;
//调用时局部变量
pAry[i].onclick =
function
() {
alert(temp);
}
})();
}
}
|
5, add a layer of closures, return a function as a response event (note the subtle difference from 3)
12345678910 |
function
init5() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
pAry[i].onclick =
function
(arg) {
return
function
() {
//返回一个函数
alert(arg);
}
}(i);
}
}
|
And then we found two kinds of
6, with the function implementation, in fact, each generation of an instance of the functions will produce a closure
123456 |
function
init6() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var
i=0; i<pAry.length; i++ ) {
pAry[i].onclick =
new
Function(
"alert("
+ i +
");"
);
//new一次就产生一个函数实例
}
}
|
7, with the function to achieve, pay attention to the difference with 6
123456 |
function
init7() {
var
pAry = document.getElementsByTagName(
"p"
);
for
(
var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = Function(
‘alert(‘
+i+
‘)‘
);
}
}
|
JavaScript closures Demo "Go"