分析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插件扩展识别浏览器内核与外壳的类型和版本的实现代码
Oct 22 Javascript
Jquery实现点击按钮,连续地向textarea中添加值的实例代码
Mar 08 Javascript
jQuery使用zTree插件实现树形菜单和异步加载
Feb 25 Javascript
Bootstrap实现弹性搜索框
Jul 11 Javascript
简单的js表格操作
Sep 24 Javascript
vue的props实现子组件随父组件一起变化
Oct 27 Javascript
重学 JS:为啥 await 不能用在 forEach 中详解
Apr 15 Javascript
js中比较两个对象是否相同的方法示例
Sep 02 Javascript
JS正则表达式常见函数与用法小结
Apr 13 Javascript
原生js实现简单轮播图
Oct 26 Javascript
详解Vue的options
May 15 Vue.js
JavaScript 中for/of,for/in 的详细介绍
Nov 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
在WordPress中使用wp_count_posts函数来统计文章数量
2016/01/05 PHP
PHP设计模式之单例模式原理与实现方法分析
2018/04/25 PHP
ThinkPHP5.0框架控制器继承基类和自定义类示例
2018/05/25 PHP
PHP实现的超长文本分页显示功能示例
2018/06/04 PHP
Laravel使用RabbitMQ的方法示例
2019/06/18 PHP
popdiv
2006/07/14 Javascript
IE和FireFox(FF)中js和css的不同
2009/04/13 Javascript
javascript打印html内容功能的方法示例
2013/11/28 Javascript
js实现无限级树形导航列表效果代码
2015/09/23 Javascript
jquery实现触发时更新下拉列表内容的方法
2015/12/02 Javascript
BootStrap的select2既可以查询又可以输入的实现代码
2017/02/17 Javascript
详谈表单格式化插件jquery.serializeJSON
2017/06/23 jQuery
HTML5+JS+JQuery+ECharts实现异步加载问题
2017/12/16 jQuery
Vue.js做select下拉列表的实例(ul-li标签仿select标签)
2018/03/02 Javascript
详解微信小程序canvas圆角矩形的绘制的方法
2018/08/22 Javascript
AngularJS 事件发布机制
2018/08/28 Javascript
vue中使用百度脑图kityminder-core二次开发的实现
2019/09/26 Javascript
Python 错误和异常小结
2013/10/09 Python
python3使用urllib模块制作网络爬虫
2016/04/08 Python
python机器学习理论与实战(一)K近邻法
2021/01/28 Python
pandas 两列时间相减换算为秒的方法
2018/04/20 Python
Python实现的求解最小公倍数算法示例
2018/05/03 Python
python2与python3中关于对NaN类型数据的判断和转换方法
2018/10/30 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
Python迭代器Iterable判断方法解析
2020/03/16 Python
scrapy爬虫:scrapy.FormRequest中formdata参数详解
2020/04/30 Python
python产生模拟数据faker库的使用详解
2020/11/04 Python
html5 Canvas画图教程(6)—canvas里画曲线之arcTo方法
2013/01/09 HTML / CSS
美国杂志订阅折扣与优惠网站:Magazines.com
2016/08/31 全球购物
《小山羊和小灰兔》教学反思
2014/02/19 职场文书
汽车机修工岗位职责
2014/03/06 职场文书
低碳环保口号
2014/06/12 职场文书
企业委托书范本
2014/09/13 职场文书
教师党员自我剖析材料
2014/09/29 职场文书
大学生简历自我评价2015
2015/03/03 职场文书
分享几个JavaScript运算符的使用技巧
2021/04/24 Javascript