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”

结语:js中作用域链与闭包的知识很重要,虽然在此没有讲,其实是害怕讲不明白,反而误导了大家

以上这篇js闭包引起的事件注册问题介绍就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
window.addeventjs事件驱动函数集合addEvent等
Feb 19 Javascript
判断用户是否在线的代码
Mar 05 Javascript
javascript学习笔记(十四) window对象使用介绍
Jun 20 Javascript
intro.js 页面引导简单用法 分享
Aug 06 Javascript
jquery新的绑定事件机制on方法的使用方法
Apr 15 Javascript
非常实用的js验证框架实现源码 附原理方法
Jun 08 Javascript
ES6中module模块化开发实例浅析
Apr 06 Javascript
xmlplus组件设计系列之路由(ViewStack)(7)
May 02 Javascript
Vue组件中slot的用法
Jan 30 Javascript
js将键值对字符串转为json字符串的方法
Mar 30 Javascript
通过jquery获取上传文件名称、类型和大小的实现代码
Apr 19 jQuery
vue-cli webpack 引入swiper的操作方法
Sep 15 Javascript
使用postMesssage()实现跨域iframe页面间的信息传递方法
Mar 29 #Javascript
js滚动条平滑移动示例代码
Mar 29 #Javascript
JavaScript头像上传插件源码分享
Mar 29 #Javascript
js解决movebox移动问题
Mar 29 #Javascript
javascript中不易分清的slice,splice和split三个函数
Mar 29 #Javascript
分析js闭包引起的事件注册问题
Mar 29 #Javascript
使用postMesssage()实现iframe跨域页面间的信息传递
Mar 29 #Javascript
You might like
PHP定义字符串的四种方式详解
2018/02/06 PHP
PHP 7.4中使用预加载的方法详解
2019/07/08 PHP
php实现文件上传基本验证
2020/03/04 PHP
js DOM的学习笔记
2011/12/22 Javascript
AngularJS表单编辑提交功能实例
2015/02/13 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
jQuery的$.extend 浅拷贝与深拷贝
2017/03/08 Javascript
vue的Virtual Dom实现snabbdom解密
2017/05/03 Javascript
webpack教程之webpack.config.js配置文件
2017/07/05 Javascript
JS实现快速比较两个字符串中包含有相同数字的方法
2017/09/11 Javascript
vue2 router 动态传参,多个参数的实例
2017/11/10 Javascript
为什么Vue3.0使用Proxy实现数据监听(defineProperty表示不背这个锅)
2019/10/14 Javascript
详解如何在JS代码中消灭for循环
2019/12/11 Javascript
python 数据加密代码
2008/12/24 Python
django 常用orm操作详解
2017/09/13 Python
Python3.4 tkinter,PIL图片转换
2018/06/21 Python
python判断设备是否联网的方法
2018/06/29 Python
python使用suds调用webservice接口的方法
2019/01/03 Python
基于wxPython的GUI实现输入对话框(1)
2019/02/27 Python
python如何实现不可变字典inmutabledict
2020/01/08 Python
Python3中configparser模块读写ini文件并解析配置的用法详解
2020/02/18 Python
html5 分层屏幕适配的方法
2018/03/16 HTML / CSS
html5 Canvas画图教程(7)—canvas里画曲线之quadraticCurveTo方法
2013/01/09 HTML / CSS
浅谈Html5中视频 音频标签 进度条的问题
2016/07/26 HTML / CSS
Waterford美国官网:爱尔兰水晶制品品牌
2017/04/26 全球购物
利物浦足球俱乐部官方网上商店:Liverpool FC Official Store
2018/01/13 全球购物
苏格兰领先的多渠道鞋店:Begg Shoes
2019/10/22 全球购物
杰夫·班克斯男士服装网上商店:Jeff Banks
2019/10/24 全球购物
一些高难度的SQL面试题
2016/11/29 面试题
艾滋病宣传活动总结
2014/05/08 职场文书
应届大专生自荐书
2014/06/16 职场文书
2015年幼儿园后勤工作总结
2015/04/25 职场文书
个人工作违纪检讨书
2015/05/05 职场文书
Centos环境下Postgresql 安装配置及环境变量配置技巧
2021/05/18 PostgreSQL
浅析Python中的套接字编程
2021/06/22 Python
docker 制作mysql镜像并自动安装
2022/05/20 Servers