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+')')  
  }   
}  

Related articles: