On JavaScript for Cyclic Closure
- 2021-06-29 10:12:29
- OfStack
A netizen asked a question, like the following html, why do you output 5 for each time instead of clicking on each p to get the corresponding 1, 2, 3, 4, 5 for alert?
<html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> Closure Demo </title>
<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>
</head>
<body onload="init();">
<p> product 1</p>
<p> product 2</p>
<p> product 3</p>
<p> product 4</p>
<p> product 5</p>
</body>
</html>
There are several solutions
1. Save variable i on each paragraph object (p)
function init() {
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 variable i in anonymous function itself
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;
}
}
3. Add a layer closure and i passes it as a function parameter to the inner function
function init3() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function(arg){
pAry[i].onclick = function() {
alert(arg);
};
})(i);// Call-time parameters
}
}
4. Layer 1 closure, i passed to memory function as local variable
function init4() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function () {
var temp = i;// Local variable on call
pAry[i].onclick = function() {
alert(temp);
}
})();
}
}
5. Add a layer closure and return a function as a response event (note the subtle difference from 3)
function init5() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function(arg) {
return function() {// Return 1 Functions
alert(arg);
}
}(i);
}
}
6. Implemented with Function, virtually one closure is generated for each function instance
function init6() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = new Function("alert(" + i + ");");//new1 Secondary generation 1 Function instances
}
}
7. Implement with Function, note the difference with 6
function init7() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = Function('alert('+i+')')
}
}