分析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 相关文章推荐
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
May 24 Javascript
IE不支持getElementsByClassName最终完美解决方案
Dec 17 Javascript
js控制滚动条缓慢滚动到顶部实现代码
Mar 20 Javascript
使用CoffeeScrip优美方式编写javascript代码
Oct 28 Javascript
谈谈javascript中使用连等赋值操作带来的问题
Nov 26 Javascript
让图片跳跃起来  javascript图片轮播特效
Feb 16 Javascript
jQuery Datatable 多个查询条件自定义提交事件(推荐)
Aug 24 jQuery
从零开始在NPM上发布一个Vue组件的方法步骤
Dec 20 Javascript
微信小程序 生成携带参数的二维码
Oct 23 Javascript
详解Vue的watch中的immediate与watch是什么意思
Dec 30 Javascript
浅析TypeScript 命名空间
Mar 19 Javascript
angula中使用iframe点击后不执行变更检测的问题
May 10 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下打开phpMyAdmin出现403错误的问题解决方法
2013/05/23 PHP
一个经典的PHP文件上传类分享
2014/11/18 PHP
PHP加密解密字符串汇总
2015/04/26 PHP
使用PHP编写发红包程序
2015/07/22 PHP
php解压缩zip和rar压缩包文件的方法
2019/07/10 PHP
用JavaScript调用WebService的示例
2008/04/07 Javascript
javascript得到XML某节点的子节点个数的脚本
2008/10/11 Javascript
javascript 函数调用规则
2009/08/26 Javascript
商城常用滚动的焦点图效果代码简单实用
2013/03/28 Javascript
JavaScript实现斗地主游戏的思路
2016/02/29 Javascript
jQuery中on绑定事件后引发的事件冒泡问题如何解决
2016/05/25 Javascript
详解vue-cli快速构建项目以及引入bootstrap、jq
2017/05/26 Javascript
Node.js+Express+MySql实现用户登录注册功能
2017/07/10 Javascript
AngularJS使用Filter自定义过滤器控制ng-repeat去除重复功能示例
2018/04/21 Javascript
JS实现处理时间,年月日,星期的公共方法示例
2019/05/31 Javascript
no-vnc和node.js实现web远程桌面的完整步骤
2019/08/11 Javascript
vue 实现v-for循环回来的数据动态绑定id
2019/11/07 Javascript
vue实现lodop打印功能的示例
2020/11/11 Javascript
[04:45]DOTA2-DPC中国联赛正赛 iG vs LBZS 赛后选手采访
2021/03/11 DOTA
python3图片转换二进制存入mysql
2013/12/06 Python
Python实现二维数组按照某行或列排序的方法【numpy lexsort】
2017/09/22 Python
根据DataFrame某一列的值来选择具体的某一行方法
2018/07/03 Python
Python使用numpy产生正态分布随机数的向量或矩阵操作示例
2018/08/22 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
python数据化运营的重要意义
2019/11/25 Python
Python字符串的修改方法实例
2019/12/19 Python
python保留格式汇总各部门excel内容的实现思路
2020/06/01 Python
CSS3实现自定义Checkbox特效实例代码
2017/04/24 HTML / CSS
Perfume’s Club意大利官网:欧洲美妆电商
2019/05/03 全球购物
单位人事专员介绍信
2014/01/11 职场文书
机电一体化专业求职信
2014/07/22 职场文书
私人房屋买卖协议书
2014/10/04 职场文书
python3实现Dijkstra算法最短路径的实现
2021/05/12 Python
Python Pycharm虚拟下百度飞浆PaddleX安装报错问题及处理方法(亲测100%有效)
2021/05/24 Python
html form表单基础入门案例讲解
2021/07/21 HTML / CSS
Nginx虚拟主机的搭建的实现步骤
2022/01/18 Servers