看此篇文章前,请确保已有闭包的知识储备~

一、问题引入

页面上五个完全相同的按钮,现在想实现点哪个按钮,哪个按钮就弹出自己是第几个。

<button>click me!</button>
<button>click me!</button>
<button>click me!</button>
<button>click me!</button>
<button>click me!</button>

乍一看,这不是很简单嘛,一个循环+一个绑定事件就搞定:

var btns = document.getElementsByTagName("button");
for (var = 0; i < btns.length; i++) {btns[i].onclick = function() {  console.log(i);}
}

兴高采烈的点开按钮,你却发现每个按钮点出来都弹的是5

原来是因为:
一般单击按钮,都只能在循环结束后。
等到循环后再去单击按钮,调用的就是按钮上提前保存的事件处理函数

二、回调函数等待队列

这个时候我们就要了解一个概念,在程序执行中不仅有主程序,还有一个主程序之外的队列,回调函数等待队列

只有主程序中所有代码都执行完,才能从回调队列中取函数,进入主程序执行。

以上述问题作为例子,程序运行图如下:
主程序循环之后i=5,然后再去执行回调函数等待队列,故所有console.log输出结果都为5

三、解决方案

方法一:闭包函数

使用 匿名函数自调用,每次将传入的值i放在局部变量中,并使局部变量和onclick事件形成闭包,局部变量被永久保存起来。

此处闭包中函数不用返回到外部的原因:
按钮一直存在,属于全局定义,不用return

var btns = document.getElementsByTagName("button");for (var i = 0; i < btns.length; i++) {(function(i){      //循环几次,生成几个单独的闭包// var i; //如果有形参,相当于局部变量btns[i].onclick = function() {  alert(i);}})(i);
}
console.log(i)

方法二:let

let在底层自动转换为匿名函数自调用,其实等效于方法一

当let碰上for:匿名函数自调擅自加工加入了循环变量,此处为i

var btns = document.getElementsByTagName("button");// let底层原理就是匿名函数自调,闭包
for (let i = 0; i < btns.length; i++) {// (function(i){ btns[i].onclick = function() {  console.log(i);}// })(i);
}

ES6之let原理+回调函数等待队列——五个完全相同的按钮,点第i个按钮弹出i相关推荐

  1. 写一个函数,用户输入一个数判断是否是素数,并返弹出回值(又叫质数,只能被1和自身整数的数)

    // 写一个函数,用户输入一个数判断是否是素数,并返弹出回值(又叫质数,只能被1和自身整数的数)function isPrime(num) {for (var i = 2; i < num; i ...

  2. Javascript第四章定义函数的形式、回调函数第五课

    两者的区别: 第一种方法:函数声明在编写时可以先调用,再声明: 第二种方法:函数表达式必须先定义,再调用 更多免费教学文章请关注这里 函数的回调 主要的理解: 当用户用的时候,不是直接触发的状态,当他 ...

  3. 【黑马pink老师函数及应用作业】写一个函数,用户输入任意两个数字的最大值,并能弹出运算后的结果

    <script>var num1 = prompt('请输入相比较的数值1');var num2 = prompt('请输入相比较的数值2');function num(num1,num2 ...

  4. C语言 回调函数 callback - C语言零基础入门教程

    目录 一.回调函数原理 二.回调函数简介 1.函数指针 2.指针函数 3.回调函数解释 三.回调函数实战 四.回调函数使用总结 五.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 ...

  5. RTX5 | 消息队列04 - (实战技巧)串口中断回调函数ISR同步线程

    文章目录 一.前言 二.实验目的 三.API 3.2.osMessageQueueGet 四.代码 4.1.main.h 4.2.stm32f1xx.it.c 4.3.main.c 五.Event R ...

  6. mysql 1539_MySQL:半同步(三)从库端初始化和回调函数

    源码版本5.7.29 一.全局变量 semisync_slave_plugin.cc ReplSemiSyncSlave repl_semisync; /* indicate whether or n ...

  7. Opencv鼠标回调函数

    1.目的 读取一张图片,在该图片上截取一个ROI区域,将截取的图像在新窗口显示,并可以保存至工程目录下. 2.实现环境 C++.VS2017.opencv 3.回调函数原理 回调函数就是一个通过函数指 ...

  8. 函数指针--Nginx和Redis中两种回调函数写法

    1.Nginx和Redis中两种回调函数写法 #include <stdio.h>//仿Nginx风格 //结构外声明函数指针类型 typedef void (*ngx_connectio ...

  9. 菜鸟学习笔记:Java基础篇5(抽象类与接口、回调函数、内部类)

    菜鸟学习笔记:Java面向对象篇下 抽象类 接口 回调函数 内部类 成员内部类 匿名内部类 抽象类 通过前面知识的学习,抽象类这个概念应该不难理解,但比较容易和后面要说的接口混淆,而且在面试中也比较爱 ...

最新文章

  1. PX4编写msg文件
  2. linux挂载到哪个分区,Linux中直接挂载硬盘和挂载分区有什么区别?
  3. ​常用的连续概率分布汇总
  4. C++ 虚函数表解析
  5. iOS 12 真机调试 Xcode 9 提示 Could not locate device support files.
  6. 鸿蒙系统海外名称,新商标表明华为鸿蒙系统在海外或叫做“Harmony OS”
  7. 【算法竞赛学习】二手车交易价格预测-Baseline
  8. 家用路由器及NAT协议
  9. 追光的人beta冲刺总结
  10. Getting Real ——把握现实
  11. 千万别把WIFI玩坏了!关于WIFI的新鲜玩法和商业模式探讨
  12. 2020年,微信的基地属性正在悄然转向
  13. 数据质量监控Griffin——使用
  14. Linux系统中 如何系统排错 二之文件引导阶段(引导文件丢失)!
  15. pip安装GeoIP时报fatal error: GeoIP.h: No such file or directory
  16. 要嫁就嫁程序员:那些你不理解的真实的他们。
  17. cacti mysql 修复_cacti数据库修复
  18. java毕业设计服装生产管理系统mybatis+源码+调试部署+系统+数据库+lw
  19. oracle层级计算推演,(特价书)Oracle 高性能SQL引擎剖析:SQL优化与调优机制详解(资深Oracle专家黄玮十年磨一剑,盖国强作序力荐)(china-pub首发)...
  20. Elitebook 735 更换键盘

热门文章

  1. [ES6] 细化ES6之 -- Class关键字
  2. 再见2019,拥抱2020
  3. 精确定位网页中各个元素的位置
  4. idea怎么导入jxl.jar库
  5. 汉堡王什么汉堡好吃_如何制作汉堡的汉堡胚?做汉堡胚需要注意什么?
  6. MyBatis复习(五):获取多表关联查询结果
  7. 狂野飙车9手游服务器维护,狂野飙车9_狂野飙车9公益服_变态版狂野飙车9_狂野飙车9官网_9917游戏...
  8. android picasso 三级缓存,Android中图片的三级缓存浅析
  9. php学习总结,PHP学习的技巧和学习的要素总结
  10. java纪元时间_Java实现纪元秒和本地日期时间互换的方法【经典实例】