分析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 相关文章推荐
MooTools 1.2中的Drag.Move来实现拖放
Sep 15 Javascript
js控制表单操作的常用代码小结
Aug 15 Javascript
javascript简单实现表格行间隔显示颜色并高亮显示
Nov 29 Javascript
jquery获取radio值实例
Oct 16 Javascript
JS实现当前页居中分页效果的方法
Jun 18 Javascript
jquery实现简单的遮罩层
Jan 08 Javascript
jQuery Ajax 加载数据时异步显示加载动画
Aug 01 Javascript
js实现京东轮播图效果
Jun 30 Javascript
web前端页面生成exe可执行文件的方法
Feb 08 Javascript
纯js封装的ajax功能函数与用法示例
May 14 Javascript
vue-cli中vue本地实现跨域调试接口
Jan 16 Javascript
VUE.js实现动态设置输入框disabled属性
Oct 28 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面向对象全攻略 (一) 面向对象基础知识
2009/09/30 PHP
PHP迅雷、快车、旋风下载专用链转换代码
2010/06/15 PHP
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
javascript自执行函数之伪命名空间封装法
2010/12/25 Javascript
Ajax执行顺序流程及回调问题分析
2012/12/10 Javascript
jquery 模板的应用示例
2013/11/12 Javascript
setTimeout()与setInterval()方法区别介绍
2013/12/24 Javascript
使用javascript控制cookie显示和隐藏背景图
2014/02/12 Javascript
jquery实现个人中心导航菜单效果和美观都非常不错
2014/09/02 Javascript
javascript实现网页字符定位的方法
2015/07/14 Javascript
使用jQuery操作HTML的table表格的实例解析
2016/03/13 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
2016/05/12 Javascript
JavaScript Ajax编程 应用篇
2016/07/02 Javascript
NodeJs的优势和适合开发的程序
2016/08/14 NodeJs
Vue.js路由组件vue-router使用方法详解
2016/12/02 Javascript
AngularJS打开页面隐藏显示表达式用法示例
2016/12/25 Javascript
详解如何使用Vue2做服务端渲染
2017/03/29 Javascript
angularjs下拉框空白的解决办法
2017/06/20 Javascript
JS实现页面打印(整体、局部)
2017/08/18 Javascript
微信小程序项目实践之验证码倒计时功能
2018/07/18 Javascript
Angular5集成eventbus的示例代码
2018/07/19 Javascript
Koa 中的错误处理解析
2019/04/09 Javascript
vue elementUI 表单校验功能之数组多层嵌套
2019/06/04 Javascript
详解vue3.0 diff算法的使用(超详细)
2020/07/01 Javascript
Python常用的文件及文件路径、目录操作方法汇总介绍
2015/05/21 Python
Python FTP文件定时自动下载实现过程解析
2019/11/12 Python
移动端rem布局的两种实现方法
2018/01/03 HTML / CSS
详解canvas drawImage()方法绘制图片不显示的问题
2018/10/08 HTML / CSS
HTML5梦幻之旅——炫丽的流星雨效果实现过程
2013/08/06 HTML / CSS
Html5移动端适配IphoneX等机型的方法
2019/06/25 HTML / CSS
美国最便宜的旅游网站:CheapTickets
2017/07/09 全球购物
浙江文明网签名寄语
2014/01/18 职场文书
精彩的广告词
2014/03/19 职场文书
农村党建工作汇报材料
2014/10/27 职场文书
公务员个人考察材料
2014/12/23 职场文书
win10此电脑打不开怎么办 win10双击此电脑无响应的解决办法
2022/07/23 数码科技