分析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 Tools tab(幻灯片)
Jul 14 Javascript
5种处理js跨域问题方法汇总
Dec 04 Javascript
Bootstrap每天必学之简单入门
Nov 19 Javascript
AngularJS equal比较对象实例详解
Sep 14 Javascript
JavaScript 字符串常用操作小结(非常实用)
Nov 30 Javascript
vue实现简单实时汇率计算功能
Jan 15 Javascript
微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能示例
Dec 11 Javascript
vue实现路由懒加载及组件懒加载的方式
Jun 11 Javascript
jquery ui 实现 tab标签功能示例【测试可用】
Jul 25 jQuery
Webpack设置环境变量的一些误区详解
Dec 19 Javascript
用js编写留言板
Mar 17 Javascript
Vue3不支持Filters过滤器的问题
Sep 24 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
使用eAccelerator加密PHP程序
2008/10/03 PHP
php 删除无限级目录与文件代码共享
2008/11/22 PHP
php 中文字符入库或显示乱码问题的解决方法
2010/04/12 PHP
让PHP开发者事半功倍的十大技巧小结
2010/04/20 PHP
php HandlerSocket的使用
2011/05/02 PHP
php模块memcache和memcached区别分析
2011/06/14 PHP
javascript Object与Function使用
2010/01/11 Javascript
javascript改变position值实现菜单滚动至顶部后固定
2013/01/18 Javascript
Js点击弹出下拉菜单效果实例
2013/08/12 Javascript
JS将数字转换成三位逗号分隔的样式(示例代码)
2014/02/19 Javascript
node.js中的buffer.toJSON方法使用说明
2014/12/14 Javascript
js实现表单提交后不重新刷新当前页面
2016/11/30 Javascript
完美解决spring websocket自动断开连接再创建引发的问题
2017/03/02 Javascript
Three.js获取鼠标点击的三维坐标示例代码
2017/03/24 Javascript
利用Angular.js编写公共提示模块的方法教程
2017/05/28 Javascript
基于jquery实现左右上下移动效果
2018/05/02 jQuery
修改vue+webpack run build的路径方法
2018/09/01 Javascript
mpvue 单文件页面配置详解
2018/12/02 Javascript
vue通信方式EventBus的实现代码详解
2019/06/10 Javascript
js数组相减简单示例【删除a数组所有与b数组相同元素】
2020/03/04 Javascript
三剑客:offset、client和scroll还傻傻分不清?
2020/12/04 Javascript
[03:42]2014DOTA2西雅图国际邀请赛 Navi战队巡礼
2014/07/07 DOTA
[59:35]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第二局
2016/03/04 DOTA
使用Python读写文本文件及编写简单的文本编辑器
2016/03/11 Python
Python实现堡垒机模式下远程命令执行操作示例
2019/05/09 Python
Python读取stdin方法实例
2019/05/24 Python
python三大神器之fabric使用教程
2019/06/10 Python
Python 3.8 新功能来一波(大部分人都不知道)
2020/03/11 Python
初学者学习Python好还是Java好
2020/05/26 Python
Keras自动下载的数据集/模型存放位置介绍
2020/06/19 Python
python解决OpenCV在读取显示图片的时候闪退的问题
2021/02/23 Python
一套PHP的笔试题
2013/05/31 面试题
安全月活动总结
2014/05/05 职场文书
2014工程部年度工作总结
2014/12/17 职场文书
2016秋季田径运动会广播稿
2015/12/21 职场文书
适合毕业生创业的项目怎么找?
2019/08/08 职场文书