分析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 DOM事件模型的两件事
Jul 22 Javascript
ExtJs使用总结(非常详细)
Mar 22 Javascript
表单验证的完整应用案例探讨
Mar 29 Javascript
html5的自定义data-*属性和jquery的data()方法的使用示例
Aug 21 Javascript
JavaScript中的逻辑判断符&amp;&amp;、||与!介绍
Dec 31 Javascript
js同源策略详解
May 21 Javascript
js实现用户离开页面前提示是否离开此页面的方法(包括浏览器按钮事件)
Jul 18 Javascript
关于动态生成dom绑定事件失效的原因及解决方法
Aug 06 Javascript
JavaScript数组和对象的复制
Mar 21 Javascript
bootstrap table实现单击单元格可编辑功能
Mar 28 Javascript
vue中axios的二次封装实例讲解
Oct 14 Javascript
JS监听Esc 键触发事键
Apr 14 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
解决出现SoapFault (looks like we got no XML document)的问题
2017/06/24 PHP
PHP+mysql防止SQL注入的方法小结
2019/04/27 PHP
PHP使用DOM对XML解析处理操作示例
2019/07/04 PHP
prototype 1.5 &amp; scriptaculous 1.6.1 学习笔记
2006/09/07 Javascript
根据一段代码浅谈Javascript闭包
2010/12/14 Javascript
javascript获取元素CSS样式代码示例
2013/11/28 Javascript
jQuery中fadeOut()方法用法实例
2014/12/24 Javascript
JS+CSS实现自适应选项卡宽度的圆角滑动门效果
2015/09/15 Javascript
封装好的javascript前端分页插件pagination
2016/01/04 Javascript
Node.js模块封装及使用方法
2016/03/06 Javascript
jQuery图片左右滚动代码 有左右按钮实例
2016/06/20 Javascript
js实现小窗口拖拽效果
2016/12/03 Javascript
AngularJS监听路由变化的方法
2017/03/07 Javascript
Vue常用指令V-model用法
2017/03/08 Javascript
JS判断两个对象内容是否相等的方法示例
2017/04/10 Javascript
使用layui定义一个模块并使用的例子
2019/09/14 Javascript
python中的字典使用分享
2016/07/31 Python
Python简单遍历字典及删除元素的方法
2016/09/18 Python
不要用强制方法杀掉python线程
2017/02/26 Python
python 矩阵增加一行或一列的实例
2018/04/04 Python
python 获取图片分辨率的方法
2019/01/08 Python
python实现函数极小值
2019/07/10 Python
python wxpython 实现界面跳转功能
2019/12/17 Python
基于FME使用Python过程图解
2020/05/13 Python
Keras模型转成tensorflow的.pb操作
2020/07/06 Python
Python进行特征提取的示例代码
2020/10/15 Python
全方位了解CSS3的Regions扩展
2015/08/07 HTML / CSS
大学生自我鉴定
2013/12/16 职场文书
讲文明树新风公益广告宣传方案
2014/02/25 职场文书
酒店管理毕业生自荐信
2014/05/25 职场文书
119消防日活动总结
2014/08/29 职场文书
考生诚信考试承诺书
2015/04/29 职场文书
互联网的下一个风口:新的独角兽将诞生
2019/08/02 职场文书
pytorch中的torch.nn.Conv2d()函数图文详解
2022/02/28 Python
sql server偶发出现死锁的解决方法
2022/04/10 SQL Server
Python使用MapReduce进行简单的销售统计
2022/04/22 Python