分析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 相关文章推荐
JS获取dom 对象 ajax操作 读写cookie函数
Nov 18 Javascript
浏览器图片选择预览、旋转、批量上传的JS代码实现
Dec 04 Javascript
JavaScript获取网页、浏览器、屏幕高度和宽度汇总
Dec 18 Javascript
在localStorage中存储对象数组并读取的方法
Sep 24 Javascript
详解js正则表达式验证时间格式xxxx-xx-xx形式
Feb 09 Javascript
vue.js实现的经典计算器/科学计算器功能示例
Jul 11 Javascript
Vue实现简单分页器
Dec 29 Javascript
vue-cli3+typescript新建一个项目的思路分析
Aug 06 Javascript
three.js着色器材质的内置变量示例详解
Aug 16 Javascript
vue 将多个过滤器封装到一个文件中的代码详解
Sep 05 Javascript
jQuery实现容器间的元素拖拽功能
Dec 01 jQuery
jenkins自动构建发布vue项目的方法步骤
Jan 04 Vue.js
使用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 操作文件的一些FAQ总结
2009/02/12 PHP
PHP实现抓取HTTPS内容
2014/12/01 PHP
php三元运算符知识汇总
2015/07/02 PHP
Yii控制器中filter过滤器用法分析
2016/07/15 PHP
PHP实现驼峰样式字符串(首字母大写)转换成下划线样式字符串的方法示例
2017/08/10 PHP
jQuery 标题的自动翻转实现代码
2009/10/14 Javascript
javascript学习基础笔记之DOM对象操作
2011/11/03 Javascript
ASP.NET jQuery 实例18 通过使用jQuery validation插件校验DropDownList
2012/02/03 Javascript
Angularjs中如何使用filterFilter函数过滤
2016/02/06 Javascript
Cookies 和 Session的详解及区别
2017/04/21 Javascript
搭建vue开发环境
2018/07/19 Javascript
js canvas实现二维码和图片合成的海报
2020/11/19 Javascript
Vue中使用canvas方法总结
2019/02/12 Javascript
微信小程序利用for循环解决内容变更问题
2020/03/05 Javascript
Vue组件通信$attrs、$listeners实现原理解析
2020/09/03 Javascript
python实现百度关键词排名查询
2014/03/30 Python
Python中的exec、eval使用实例
2014/09/23 Python
详解django中自定义标签和过滤器
2017/07/03 Python
python方向键控制上下左右代码
2018/01/20 Python
Python 在字符串中加入变量的实例讲解
2018/05/02 Python
Python 查看list中是否含有某元素的方法
2018/06/27 Python
Python使用lambda表达式对字典排序操作示例
2019/07/25 Python
python2.7的flask框架之引用js&amp;css等静态文件的实现方法
2019/08/22 Python
Python Pandas 转换unix时间戳方式
2019/12/07 Python
python print 格式化输出,动态指定长度的实现
2020/04/12 Python
python使用yaml 管理selenium元素的示例
2020/12/01 Python
谈一谈HTML5本地存储技术
2016/03/02 HTML / CSS
美国购买体育、音乐会和剧院门票网站:SelectATicket
2019/09/08 全球购物
《神奇的克隆》教学反思
2014/04/10 职场文书
服务承诺书范文
2014/05/19 职场文书
农村党支部书记党群众路线四风问题整改措施
2014/09/26 职场文书
2015年端午节活动总结
2015/02/11 职场文书
民主评议党员个人自我评价
2015/03/03 职场文书
2015年医院后勤工作总结
2015/05/20 职场文书
张丽莉观后感
2015/06/16 职场文书
JS实现简单九宫格抽奖
2022/06/28 Javascript