JavaScript闭包示例

在下面的例子中,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4。

复制代码
 1 <html>
 2 <head>
 3 <meta charset="utf-8" />
 4 <title>闭包演示</title>
 5 <style type="text/css">
 6     p {background:#ccc;}
 7 </style>
 8 <script type="text/javascript">
 9 window.onload = function() {   
10     var arr= document.getElementsByTagName("p");   
11     for( var i=0; i<arr.length; i++ ) {   
12          arr[i].onclick = function() {   
13          alert(i);   
14     }
15   }
16 }
17 </script>
18 </head>
19 <body>
20 <p>000</p>
21 <p>111</p>
22 <p>222</p>
23 <p>333</p>
24 <p>444</p>
25 </body>
26 </html> 
复制代码

原因是初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元素添加 点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。

 

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

复制代码
1  window.onload = function(){
2     var arr = document.getElementsByTagName('p');
3      for(var i=0; i<arr.length; i++){
4          arr[i].i= i;  //或 arr[i].index = i;
5              arr[i].onclick = function(){
6              alert(this.i);  //或alert(this.index);
7         }
8      }
9 }                
复制代码

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

复制代码
window.onload = function () {
  var arr= document.getElementsByTagName("p");
  for( var i=0; i<pAry.length; i++ ) {
   (function(arg){
       arr[i].onclick = function() {
          alert(arg);
       };
   })(i);//调用时参数
  }
}
复制代码

方法3:将变量 i 保存在匿名函数自身

复制代码
1 window.onload = function () {
2   var arr= document.getElementsByTagName("p");
3   for( var i=0; i<arr.length; i++ ) {
4    (arr[i].onclick = function() {
5         alert(arguments.callee.i);
6     }).i = i;
7   }
8 }

复制代码

4、加一层闭包,i 以局部变量形式传递给内层函数

复制代码
 1 window.onload = function () {
 2   var arr= document.getElementsByTagName("p");
 3   for( var i=0; i<arr.length; i++ ) {
 4     (function () {
 5       var temp = i;//调用时局部变量
 6       arr[i].onclick = function() {
 7         alert(temp);
 8       }
 9     })();
10   }
11 }
复制代码

5、加一层闭包,返回一个函数作为响应事件(注意与2的细微区别)

复制代码
 1 window.onload = function () {
 2   var arr= document.getElementsByTagName("p");
 3   for( var i=0; i<arr.length; i++ ) {
 4    arr[i].onclick = function(arg) {
 5        return function() {//返回一个函数
 6        alert(arg);
 7      }
 8    }(i);
 9   }
10 }
复制代码

6、用Function实现,实际上每产生一个函数实例就会产生一个闭包

1  window.onload = function() {
2      var arr= document.getElementsByTagName("p");
3      for( var i=0; i<arr.length; i++ ) {
4        arr[i].onclick = new Function("alert(" + i + ");"); //new一次就产生一个函数实例
5      }
6  }

 

7、用Function实现,注意与6的区别

1 window.onload = function() {
2     var arr= document.getElementsByTagName("p");
3     for( var i=0; i<arr.length; i++ ) {
4          arr[i].onclick = Function('alert('+i+')');
5     }
6 }

 

posted @   远方的远方  阅读(1469)  评论(7编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示