JavaScript for循环与闭包:解决点击事件输出错误的7种方案

作者:木棉时间:2026-10-30 09:32:07浏览:522

本文深入解析JavaScript中for循环绑定点击事件时输出固定值的经典问题。通过7种不同方案,包括变量挂载、函数参数传递、立即执行函数及Function构造函数等,详细展示如何利用闭包机制正确捕获循环变量,确保每次点击输出对应索引。

问题背景:for循环与点击事件的经典陷阱

有开发者提出一个常见疑问:在如下HTML结构中,为什么每次点击段落元素时,弹出的数值始终是5,而不是期望的对应索引1、2、3、4、5?


<html >   
<head>   
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   
<title>闭包演示</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>产品一</p>   
<p>产品二</p>   
<p>产品三</p>   
<p>产品四</p>   
<p>产品五</p>   
</body>   
</html>  

解决方案详解

针对该问题,存在多种解决思路。

方案一:将变量 i 保存给在每个段落对象(p)上

第一种方案是将变量 i 保存给在每个段落对象(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);   
   }   
 }   
}   

方案二:将变量 i 保存在匿名函数自身

第二种方案是将变量 i 保存在匿名函数自身


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;   
 }   
} 

方案三:加一层闭包,i以函数参数形式传递给内层函数

第三种方案是加一层闭包,i以函数参数形式传递给内层函数


function init3() {   
 var pAry = document.getElementsByTagName("p");   
 for( var i=0; i<pAry.length; i++ ) {   
  (function(arg){     
    pAry[i].onclick = function() {     
     alert(arg);   
    };   
  })(i);//调用时参数   
 }   
}   

方案四:加一层闭包,i以局部变量形式传递给内存函数

第四种方案是加一层闭包,i以局部变量形式传递给内存函数


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);    
   }   
  })();   
 }   
}   

方案五:加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)

第五种方案是加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)


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);   
 }   
}  

方案六:用Function实现,实际上每产生一个函数实例就会产生一个闭包

第六种方案是用Function实现,实际上每产生一个函数实例就会产生一个闭包


function init6() {   
  var pAry = document.getElementsByTagName("p");   
  for( var i=0; i<pAry.length; i++ ) {    
   pAry[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例  
  }   
}  

方案七:用Function实现,注意与6的区别

第七种方案是用Function实现,注意与6的区别


function init7() {   
  var pAry = document.getElementsByTagName("p");   
  for( var i=0; i<pAry.length; i++ ) {   
     pAry[i].onclick = Function('alert('+i+')')  
  }   
}  

以上就是小编为大家带来的浅谈JavaScript for循环 闭包全部内容了,希望大家多多支持本站~

作者最新文章