分析js闭包引起的事件注册问题


Posted in Javascript onMarch 29, 2016

背景:闲暇时间看了几篇关于js作用域链与闭包的文章,偶然又看到了之前遇到的一个问题,就是在for循环中为dom节点注册事件驱动,具体见下面代码:

<!DOCTYPE html>
<html>
 <head>
 <title>js闭包</title>
 <meta charset="utf-8" />
 </head>
 <body>
 <button id="anchor1">1</button>
 <button id="anchor2">2</button>
 <button id="anchor3">3</button>
 <script type="text/javascript" src="jquery-1.12.1.js"></script>
 <script type="text/javascript">
  function pageLoad(){
  for (var i = 1; i <=3; i++) { 
   var anchor = document.getElementById("anchor" + i);
   anchor.onclick = function () {
   console.log("anchor"+i);
   } 
  } 
  } 
  window.onload = pageLoad; 
 </script>
 </body>
</html>

按照正常的想法,结果应该是点击3个按钮分别提示“anchor1”、“anchor2”、“anchor3”;期初我也是这么认为的,但是结果却是不管点击哪个按钮,都会提示“anchor4”。

这是为什么呢?不要着急,待我们慢慢分析,这里面包含js作用域链与闭包的知识,在这里我就不详细介绍了。

首先我们看这个anchor.onclick,这是什么?这是dom0级事件处理程序啊,废话,我也知道,博主是蛇精病吗*************不要吵了,我想说的是这个anchor.onclick

是一个事件处理程序的声明,就像var name="小明"一样,这是声明了,但是还没有执行,这就是关键,我们将上面的js代码修改一下再来看看:

function pageLoad(){
  for (var i = 1; i <=3; i++) { 
  var anchor = document.getElementById("anchor" + i);
   anchor.onclick = function () {
   console.log("anchor"+i);
   } 
   if(i==2){
   debugger;//我们在这里debugger一下,然后在控制台手动触发#anchor1和#anchor2的点击事件
   }
  } 
 } 
 window.onload = pageLoad;

分析js闭包引起的事件注册问题

看到了吧,我们通过debugger让循环在i==2时停止,然后又去控制台手动触发#anchor1和#anchor2的点击事件,结果控制台打印“anchor2”。

整个的逻辑大致是这样的:anchor.onclick一直保存着i的引用,i在循环中是一直变化的,从i=1到i=4;虽然在循环的过程中,anchor.onclick曾经保存过(注意“曾经”两字),

1,2,3这三种情况,但是i最终变成了4,所以说,无论点击哪个按钮,都会输出“anchor4”

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
javascript实现unicode和字符的互相转换
Jul 18 Javascript
Jquery异步请求数据实例代码
Dec 28 Javascript
js 使FORM表单的所有元素不可编辑的示例代码
Oct 17 Javascript
仿JQuery输写高效JSLite代码的一些技巧
Jan 13 Javascript
asp.net+js实现金额格式化
Feb 27 Javascript
jQuery表单美化插件jqTransform使用详解
Apr 12 Javascript
jQuery实现获取table表格第一列值的方法
Mar 01 Javascript
bootstrap布局中input输入框右侧图标点击功能
May 16 Javascript
【经验总结】编写JavaScript代码时应遵循的14条规律
Jun 20 Javascript
原生js轮播(仿慕课网)
Feb 15 Javascript
Vue.js 2.x之组件的定义和注册图文详解
Jun 19 Javascript
Vue-cli3项目引入Typescript的实现方法
Oct 18 Javascript
使用postMesssage()实现iframe跨域页面间的信息传递
Mar 29 #Javascript
Angularjs实现多个页面共享数据的方式
Mar 29 #Javascript
jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签
Mar 29 #Javascript
JavaScript面向对象程序设计教程
Mar 29 #Javascript
jQuery实现图片加载完成后改变图片大小的方法
Mar 29 #Javascript
Web前端开发工具——bower依赖包管理工具
Mar 29 #Javascript
Jquery操作cookie记住用户名
Mar 29 #Javascript
You might like
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
PHP设计模式之装饰器模式定义与用法详解
2018/04/02 PHP
微信支付之JSAPI公众号支付详解
2019/05/15 PHP
javascript定时保存表单数据的代码
2011/03/17 Javascript
Js表格万条数据瞬间加载实现代码
2014/02/20 Javascript
浅析tr的隐藏和显示问题
2014/03/05 Javascript
实现checkbox全选、反选、取消JavaScript小脚本异常
2014/04/10 Javascript
jquery 表格排序、实时搜索表格内容(附图)
2014/05/19 Javascript
JS将滑动门改为选项卡(需鼠标点击)的实现方法
2015/09/27 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
2016/11/22 Javascript
EditPlus中的正则表达式 实战(4)
2016/12/15 Javascript
jquery UI Datepicker时间控件冲突问题解决
2016/12/16 Javascript
浅谈vue引入css,less遇到的坑和解决方法
2018/01/20 Javascript
Vue 按键修饰符处理事件的方法
2018/05/04 Javascript
vue实现全匹配搜索列表内容
2019/09/26 Javascript
js+canvas实现两张图片合并成一张图片的方法
2019/11/01 Javascript
通过实例浅析Python对比C语言的编程思想差异
2015/08/30 Python
Python3简单实例计算同花的概率代码
2017/12/06 Python
python增加矩阵维度的实例讲解
2018/04/04 Python
对pytorch网络层结构的数组化详解
2018/12/08 Python
使用Python的turtle模块画国旗
2019/09/24 Python
Python常用模块sys,os,time,random功能与用法实例分析
2020/01/07 Python
tensorflow 报错unitialized value的解决方法
2020/02/06 Python
简单了解Python多态与属性运行原理
2020/06/15 Python
经验丰富程序员才知道的8种高级Python技巧
2020/07/27 Python
CK巴西官方网站:Calvin Klein巴西
2019/07/19 全球购物
广州盈通面试题
2015/12/05 面试题
城市规划毕业生求职信
2013/10/10 职场文书
代理商会议邀请函
2014/01/27 职场文书
大二法英学生职业生涯规划范文
2014/02/27 职场文书
个人函授自我鉴定
2014/03/25 职场文书
弄虚作假心得体会
2014/09/10 职场文书
人力资源部工作计划
2019/05/14 职场文书
解析目标检测之IoU
2021/06/26 Python
python 远程执行命令的详细代码
2022/02/15 Python
Golang map映射的用法
2022/04/22 Golang