分析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加解密功能页面
Dec 12 Javascript
在jQuery1.5中使用deferred对象 着放大镜看Promise
Mar 12 Javascript
Table冻结表头示例代码
Aug 20 Javascript
javascript实现图片延迟加载方法汇总(三种方法)
Aug 27 Javascript
JS实现黑客帝国文字下落效果
Sep 01 Javascript
jQuery实现点击任意位置弹出层外关闭弹出层效果
Oct 19 Javascript
jquery dataview数据视图插件使用方法
Dec 23 Javascript
利用Angular2的Observables实现交互控制的方法
Dec 27 Javascript
vue2.0+vue-router构建一个简单的列表页的示例代码
Feb 13 Javascript
es6中比较有用的7个技巧小结
Jul 12 Javascript
js实现滑动进度条效果
Aug 21 Javascript
JavaScript实现轮播图效果
Oct 30 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
星际争霸教主Flash的ID由来:你永远不会知道他之前的ID是www!
2019/01/18 星际争霸
提问的智慧
2006/10/09 PHP
php 正则 过滤html 的超链接
2009/06/02 PHP
基于OpenCV的PHP图像人脸识别技术
2009/10/11 PHP
php断点续传之如何分割合并文件
2014/03/22 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
PHP+AJAX 投票器功能
2017/11/11 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
ko knockoutjs动态属性绑定技巧应用
2012/11/14 Javascript
谷歌地图打不开的解决办法
2014/08/07 Javascript
基于RequireJS和JQuery的模块化编程——常见问题全面解析
2016/04/14 Javascript
JS+HTML5实现的前端购物车功能插件实例【附demo源码下载】
2016/10/17 Javascript
JS实现点击Radio动态更新table数据
2017/07/18 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
2017/07/21 Javascript
Vue服务器渲染Nuxt学习笔记
2018/01/31 Javascript
Node.js使用supervisor进行开发中调试的方法
2019/03/26 Javascript
使用vuex存储用户信息到localStorage的实例
2019/11/11 Javascript
解决vue elementUI中table里数字、字母、中文混合排序问题
2020/01/07 Javascript
JS中间件设计模式的深入探讨与实例分析
2020/04/11 Javascript
[43:43]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第三场 11.29
2020/12/02 DOTA
在Python中使用NLTK库实现对词干的提取的教程
2015/04/08 Python
Python 内置函数memoryview(obj)的具体用法
2017/11/23 Python
python指定写入文件时的编码格式方法
2018/06/07 Python
Python 虚拟空间的使用代码详解
2019/06/10 Python
python标准库OS模块函数列表与实例全解
2020/03/10 Python
基于python实现检索标记敏感词并输出
2020/05/07 Python
Python txt文件常用读写操作代码实例
2020/08/03 Python
Python filter过滤器原理及实例应用
2020/08/18 Python
世界顶级足球门票网站:Live Football Tickets
2017/10/14 全球购物
电子商务专业自我鉴定
2013/12/18 职场文书
酒店总经理欢迎词
2014/01/15 职场文书
管理建议书范文
2014/05/13 职场文书
小学教师培训方案
2014/06/09 职场文书
英文演讲稿开场白
2014/08/25 职场文书
先进班集体申报材料
2014/12/26 职场文书
《废话连篇——致新手》——chinapizza
2022/04/05 无线电