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">functioninit() { varpAry = document.getElementsByTagName("p"); for( vari=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 |
functioninit1() { varpAry = document.getElementsByTagName("p"); for( vari=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 |
functioninit2() { varpAry = document.getElementsByTagName("p"); for( vari=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 |
functioninit3() { varpAry = document.getElementsByTagName("p"); for( vari=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 |
functioninit4() { varpAry = document.getElementsByTagName("p"); for( vari=0; i<pAry.length; i++ ) { (function() { vartemp = 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 |
functioninit5() { varpAry = document.getElementsByTagName("p"); for( vari=0; i<pAry.length; i++ ) { pAry[i].onclick = function(arg) { returnfunction() {//返回一个函数 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 |
functioninit6() { varpAry = document.getElementsByTagName("p"); for( vari=0; i<pAry.length; i++ ) { pAry[i].onclick = newFunction("alert("+ i + ");");//new一次就产生一个函数实例 }} |
7, with the function to achieve, pay attention to the difference with 6
| 123456 |
functioninit7() { varpAry = document.getElementsByTagName("p"); for( var i=0; i<pAry.length; i++ ) { pAry[i].onclick = Function(‘alert(‘+i+‘)‘); }} |
JavaScript closures Demo "Go"