The problem of js for loop output i being the same value

<html>     
<head>     
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />     
<title>Closure demonstration</title>   
</head>     
<body>     
<p>1</p>     
<p>2</p>     
<p>3</p>     
<p>4</p>     
<p>5</p>   
<script type="text/javascript">
window.onload=function() {     
    var ps = document.getElementsByTagName("p");     
    for( var i=0; i<ps.length; i++ ) {     
         ps[i].onclick = function() {     
         alert(i);     
    }     
  }     
}     
</script>   
</body>     
</html>

Reason: js event processor will not run when the thread is idle, resulting in the output of the last value of i, that is: 5

2. Solution: use closures to protect the value of variable i.
sava1: add a layer of closure, and i is passed to the inner layer function in the form of function parameter

    for( var i=0; i<ps.length; i++ ) {     
       (function(arg){         
           ps[i].onclick = function() {         
              alert(arg);     
           };     
       })(i);//Call time parameters     
      }  

//save2: add a layer of closure, and i is passed to the memory function in the form of local variable

  for( var i=0; i<ps.length; i++ ) {       
    (function () {     
      var temp = i;//Local variable on call     
      ps[i].onclick = function() {       
        alert(temp);       
      }     
    })();     
  }

//save3: add a layer of closure and return a function as the response event (note the subtle difference with 3)

for( var i=0; i<ps.length; i++ ) {       
   ps[i].onclick = function(arg) {     
       return function() {//Returns a function     
       alert(arg);     
     }     
   }(i);     
  } 

//save4: save variable i to each paragraph object (p)

for( var i=0; i<ps.length; i++ ) {     
     ps[i].i = i;     
     ps[i].onclick = function() {     
        alert(this.i);     
     }     
  }

//save5: save variable i in anonymous function itself

  for( var i=0; i<ps.length; i++ ) {       
   (ps[i].onclick = function() {     
        alert(arguments.callee.i);     
    }).i = i;     
  }          
} 

//save6: implemented with Function. In fact, each Function instance will generate a closure

for( var i=0; i<ps.length; i++ ) {       
  ps[i].onclick = new Function("alert(" + i + ");");//new generates a function instance at a time    
} 

//save7: implemented with Function, note the difference with 6

for( var i=0; i<ps.length; i++ ) {     
         ps[i].onclick = function() {     
         alert(i);     
    }   

//save8: perfect solution with Let in ES6

for( let i=0; i<ps.length; i++ ) {     
         ps[i].onclick = function() {     
         alert(i);     
}

Keywords: Javascript

Added by mattee on Sat, 04 Jan 2020 04:51:09 +0200