分析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 相关文章推荐
JQuery FlexiGrid的asp.net完美解决方案 dotNetFlexGrid-.Net原生的异步表格控件
Sep 12 Javascript
js实现点击图片将图片地址复制到粘贴板的方法
Feb 16 Javascript
jqGrid表格应用之新增与删除数据附源码下载
Dec 02 Javascript
jQuery实现的简单分页示例
Jun 01 Javascript
jquery动态遍历Json对象的属性和值的方法
Jul 27 Javascript
jQuery中常用动画效果函数(日常整理)
Sep 17 Javascript
jQuery展示表格点击变色、全选、删除
Jan 05 Javascript
详解Vue2.0里过滤器容易踩到的坑
Jun 01 Javascript
Vue中使用的EventBus有生命周期
Jul 12 Javascript
在Vue项目中,防止页面被缩放和放大示例
Oct 28 Javascript
js实现秒表计时器
Dec 16 Javascript
前端性能优化建议
Sep 17 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教程 插件机制在PHP中实现方案
2012/11/02 PHP
PHP JSON出错:Cannot use object of type stdClass as array解决方法
2014/08/16 PHP
Yii2增删改查之查询 where参数详细介绍
2016/08/08 PHP
PHP微信API接口类
2016/08/22 PHP
10个值得深思的PHP面试题
2016/11/14 PHP
PHP单文件上传原理及上传函数的封装操作示例
2019/09/02 PHP
jquery异步请求实例代码
2011/06/21 Javascript
Jquery上传插件 uploadify v3.1使用说明
2012/06/18 Javascript
jquery获取焦点和失去焦点事件代码
2013/04/21 Javascript
JS 退出系统并跳转到登录界面的实现代码
2013/06/29 Javascript
javascript setinterval 的正确语法如何书写
2014/06/17 Javascript
node.js中的console.time方法使用说明
2014/12/09 Javascript
jQuery的animate函数实现图文切换动画效果
2015/05/03 Javascript
老生常谈JavaScript 函数表达式
2016/09/01 Javascript
如何理解Vue的作用域插槽的实现原理
2017/08/19 Javascript
React如何实现浏览器打印部分内容详析
2019/05/19 Javascript
layer弹出层显示在top顶层的方法
2019/09/11 Javascript
layui清除radio的选中状态实例
2019/11/14 Javascript
js最全的数组的降维5种办法(小结)
2020/04/28 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
[42:24]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第一场 11.01
2020/11/02 DOTA
python 不关闭控制台的实现方法
2011/10/23 Python
编写Python脚本来获取Google搜索结果的示例
2015/05/04 Python
Python中使用插入排序算法的简单分析与代码示例
2016/05/04 Python
Python下载指定页面上图片的方法
2016/05/12 Python
使用python PIL库实现简单验证码的去噪方法步骤
2019/05/10 Python
Python性能分析工具Profile使用实例
2019/11/19 Python
python使用建议与技巧分享(一)
2020/08/17 Python
python闭包与引用以及需要注意的陷阱
2020/09/18 Python
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
2013/01/09 HTML / CSS
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的
2015/07/24 面试题
精神文明建设标语
2014/06/16 职场文书
英文感谢信格式
2015/01/21 职场文书
介绍长城的导游词
2015/01/30 职场文书
浪漫的婚礼主持词
2015/06/30 职场文书
复制别人的成功真的会成功吗?
2019/10/17 职场文书