分析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的开源工具PACKER2.0.2
Nov 04 Javascript
javascript的trim,ltrim,rtrim自定义函数
Sep 21 Javascript
JavaScript中继承用法实例分析
May 16 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
Jan 10 Javascript
JS跨域请求外部服务器的资源
Feb 06 Javascript
详解Angular4 路由设置相关
Aug 26 Javascript
利用百度地图API获取当前位置信息的实例
Nov 06 Javascript
JavaScript实现数值自动增加动画
Dec 28 Javascript
Vue项目分环境打包的实现步骤
Apr 02 Javascript
微信小程序实现图片上传
May 23 Javascript
react MPA 多页配置详解
Oct 18 Javascript
vue相同路由跳转强制刷新该路由组件操作
Aug 05 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 根据IP地址控制访问的代码
2010/04/22 PHP
PHP+Mysql日期时间如何转换(UNIX时间戳和格式化日期)
2012/07/15 PHP
PHP 读取Postgresql中的数组
2013/04/14 PHP
Thinkphp5结合layer弹窗定制操作结果页面
2017/07/07 PHP
thinkphp5+layui实现的分页样式示例
2019/10/08 PHP
jQuery 加上最后自己的验证
2009/11/04 Javascript
JavaScript 格式字符串的应用
2010/03/29 Javascript
jquery五角星评分插件示例分享
2014/02/21 Javascript
javascript实现拖动元素交换位置
2015/11/29 Javascript
Bootstrap3.0建站教程(一)之bootstrap表单元素排版
2016/06/01 Javascript
基于jQuery实现多标签页切换的效果(web前端开发)
2016/07/24 Javascript
vue.js中Vue-router 2.0基础实践教程
2017/05/08 Javascript
浅谈Vue.js应用的四种AJAX请求数据模式
2017/08/30 Javascript
js插件实现图片滑动验证码
2020/09/29 Javascript
微信小程序开发的基本流程步骤
2019/01/31 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
2019/04/18 Javascript
基于JavaScript伪随机正态分布代码实例
2019/11/07 Javascript
js在HTML的三种引用方式详解
2020/08/29 Javascript
JavaScript获取时区实现过程解析
2020/09/24 Javascript
html中创建并调用vue组件的几种方法汇总
2020/11/17 Javascript
Python中datetime常用时间处理方法
2015/06/15 Python
用Python的Flask框架结合MySQL写一个内存监控程序
2015/11/07 Python
Python3.6.2调用ffmpeg的方法
2019/01/10 Python
python采集百度搜索结果带有特定URL的链接代码实例
2019/08/30 Python
Python中有几个关键字
2020/06/04 Python
网页布局中CSS样式无效的十个重要原因详解
2017/08/10 HTML / CSS
HTML5 form标签之解放表单验证、增加文件上传、集成拖放的使用方法
2013/04/24 HTML / CSS
西班牙在线宠物商店:zooplus.es
2017/02/24 全球购物
Holiday Inn中国官网:IHG旗下假日酒店预订
2018/04/08 全球购物
如何在.net Winform里面显示PDF文档
2012/09/11 面试题
路政管理专业推荐信
2013/11/11 职场文书
财政局长自荐信范文
2013/12/22 职场文书
大学生饮食连锁店创业计划书
2014/01/17 职场文书
中国入世承诺
2014/04/01 职场文书
信仰心得体会
2014/09/05 职场文书
教育实习指导教师评语
2014/12/31 职场文书