分析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代码
Mar 07 Javascript
js中parseFloat(参数1,参数2)定义和用法及注意事项
Jan 27 Javascript
javascript实现右侧弹出“分享到”窗口效果
Feb 01 Javascript
javascript禁止超链接跳转的方法
Feb 02 Javascript
分享JS代码实现鼠标放在输入框上输入框和图片同时更换样式
Sep 01 Javascript
jQuery异步提交表单的两种方式
Sep 13 Javascript
简单实现JS计算器功能
Dec 21 Javascript
浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法
Mar 13 Javascript
Vue $emit $refs子父组件间方法的调用实例
Sep 12 Javascript
小程序实现五星点评效果
Nov 03 Javascript
仿ElementUI实现一个Form表单的实现代码
Apr 23 Javascript
JavaScript 数组去重详解
Sep 15 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
附件名前加网站名
2008/03/23 PHP
php图像处理函数大全(推荐收藏)
2013/07/11 PHP
PHP指定截取字符串中的中英文或数字字符的实例分享
2016/03/18 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
Javascript 面向对象 命名空间
2010/05/13 Javascript
js限制文本框输入长度两种限制方式(长度、字节数)
2012/12/19 Javascript
仿谷歌主页js动画效果实现代码
2013/07/14 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
JavaScript实现彩虹文字效果的方法
2015/04/16 Javascript
javascript实现数组中的内容随机输出
2015/08/11 Javascript
常用的JQuery函数及功能小结
2016/03/24 Javascript
JS实现将数字金额转换为大写人民币汉字的方法
2016/08/02 Javascript
jQuery Dialog 取消右上角删除按钮事件
2016/09/07 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
2016/09/17 Javascript
BootStrap下拉菜单和滚动监听插件实现代码
2016/09/26 Javascript
深入浅析Node.js单线程模型
2017/07/10 Javascript
详解.vue文件中监听input输入事件(oninput)
2017/09/19 Javascript
浅谈JsonObject中的key-value数据解析排序问题
2017/12/06 Javascript
Vue Extends 扩展选项用法完整实例
2019/09/17 Javascript
在vue中高德地图引入和轨迹的绘制的实现
2019/10/11 Javascript
基于python(urlparse)模板的使用方法总结
2017/10/13 Python
flask框架使用orm连接数据库的方法示例
2018/07/16 Python
Python sklearn KFold 生成交叉验证数据集的方法
2018/12/11 Python
jupyter修改文件名方式(TensorFlow)
2020/04/21 Python
韩国三星集团旗下时尚品牌官网:SSF SHOP
2016/08/02 全球购物
Under Armour瑞典官方网站:美国高端运动科技品牌
2018/11/21 全球购物
意大利在线药房:shop-farmacia.it
2019/03/12 全球购物
FORZIERI福喜利中国官网:奢侈品购物梦工厂
2019/05/03 全球购物
Java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类
2012/02/06 面试题
工作疏忽检讨书
2014/01/25 职场文书
《小小竹排画中游》教学反思
2014/02/26 职场文书
邻里守望志愿服务活动方案
2014/08/15 职场文书
技术入股合作协议书
2014/10/07 职场文书
装修公司工程部经理岗位职责
2015/04/09 职场文书
2015年团委副书记工作总结
2015/07/23 职场文书
Node.js实现断点续传
2021/06/23 Javascript