JavaScript的闭包特性如何给循环中的对象添加事件(一)
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。原因是初学者并未理解JavaScript的闭包特性。
1. <!DOCTYPE HTML>
2. <html>
3. <head>
4. <meta charset="utf-8" />
5. <title>闭包演示</title>
6. <style type="text/css">
7. p {background:gold;}
8. </style>
9. <script type="text/javascript">
10.function init() {
11. var pAry = document.getElementsByTagName("p");
12. for( var i=0; i<pAry.length; i++ ) {
13. pAry[i].onclick = function() {
14. alert(i);
15. }
16. }
17.}
18.</script>
19.</head>
20.<body οnlοad="init();">
21.<p>产品 0</p>
22.<p>产品 1</p>
23.<p>产品 2</p>
24.<p>产品 3</p>
25.<p>产品 4</p>
26.</body>
27.</html>
以上场景是初学者经常碰到的。即获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。
原因是初学者并未理解JavaScript的闭包特性。通过element.οnclick=function(){alert(i);}方式给元 素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。
了解了原因,下面就由几种方式可与解决:
1、将变量 i 保存给在每个段落对象(p)上
1. function init1() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. pAry[i].i = i;
5. pAry[i].onclick = function() {
6. alert(this.i);
7. }
8. }
9. }
2、将变量 i 保存在匿名函数自身
1. function init2() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. (pAry[i].onclick = function() {
5. alert(arguments.callee.i);
6. }).i = i;
7. }
8. }
3、加一层闭包,i 以函数参数形式传递给内层函数
1. function init3() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. (function(arg){
5. pAry[i].onclick = function() {
6. alert(arg);
7. };
8. })(i);//调用时参数
9. }
10.}
4、加一层闭包,i 以局部变量形式传递给内层函数
1. function init4() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. (function () {
5. var temp = i;//调用时局部变量
6. pAry[i].onclick = function() {
7. alert(temp);
8. }
9. })();
10. }
11.}
5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)
1. function init5() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. pAry[i].onclick = function(arg) {
5. return function() {//返回一个函数
6. alert(arg);
7. }
8. }(i);
9. }
10.}
6、用Function实现,实际上每产生一个函数实例就会产生一个闭包
1. function init6() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. pAry[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例
5. }
6. }
7、用Function实现,注意与6的区别
1. function init7() {
2. var pAry = document.getElementsByTagName("p");
3. for( var i=0; i<pAry.length; i++ ) {
4. pAry[i].onclick = Function('alert('+i+')');
5. }
6. }
JavaScript的闭包特性如何给循环中的对象添加事件(一)的更多相关文章
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 深入理解JavaScript的闭包特性 如何给循环中的对象添加事件(转载)
原文参考:http://blog.csdn.net/gaoshanwudi/article/details/7355794 初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数 ...
- 如何给循环中的对象添加事件--深入理解JavaScript的闭包特性
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 给ul中的li添加事件的多种方法
给ul中的li添加事件的多种方法 这是一个常见,而且典型的前端面试题 <ul> <li>11111</li> <li>22222</li> ...
- React 函数组件中对window添加事件监听resize导致回调不能获得Hooks最新状态的问题解决思路
React 函数组件中对window添加事件监听resize导致回调不能获得Hooks最新状态的问题解决思路 这几天在忙着把自己做的项目中的类组件转化为功能相同的函数组件,首先先贴一份该组件类组件的关 ...
- JavaScript的闭包特性
闭包是一个比较抽象的概念,尤其是对js新手来说.在这里,我就我个人的理解j简单谈一下: 闭包:官方解释是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部 ...
- JavaScript基础&实战(4)js中的对象、函数、全局作用域和局部作用域
文章目录 1.对象的简介 2.对象的基本操作 2.1 代码 2.2 测试结果 3.属性和属性值 3.1 代码 3.2 测试结果 4.对象的方法 4.1 代码 4.2 测试结果 5.对象字面量 5.1 ...
- PHP 循环中临时对象不销毁,会保存到一下循环,这是什么坑。。
在C++中,根本存在这种问题,一个对象或结构体在循环中声明赋值了,再一次循环就自动清空.但是在PHP中这个$monthData在下一次循环却不会重新赋值,而是保留了上一次赋值的值,这样的下一次save ...
- JavaScript中给对象添加方法
在JavaScript中,我们经常要给已定义的对象添加一些方法,如下: function circle(w,h){ this.width=w; this.height=h; ...
随机推荐
- 高强度学习训练第八天总结:MySQL的一些优化
为什么要做MYSQL优化 系统的吞吐量瓶颈往往出现在数据库的访问速度上 随着应用程序的运行,数据库中的数据会越来越多,处理时间会相应变慢. 数据是存放在磁盘上的,读写速度无法和内存相比 如何优化 设计 ...
- mac上安装npm
检查brew -v是否安装了homebrew这个macOS 缺失的软件包的管理器.如果安装,跳转到第3步,否则跳转到第二步: 安装homebrew.安装跳转到官网指导.等待安装好之后,输入brew - ...
- 抓包工具 tcpdump 用法说明
tcpdump采用命令行方式对接口的数据包进行筛选抓取,其丰富特性表现在灵活的表达式上. 不带任何选项的tcpdump,默认会抓取第一个网络接口,且只有将tcpdump进程终止才会停止抓包. 例如: ...
- mysql使用命令
1.创建用户 create user 'name'@'host' identified by 'psssword'; 2.授权 grant select, updata,insert (all) on ...
- CodeForces - 1260C(贪心+思维)
题意 https://vjudge.net/problem/CodeForces-1260C 有一串砖,凡是r的倍数而不是b的倍数必须涂红,凡是b的倍数而不是r的倍数必须涂蓝,是公倍数则选一个涂.把涂 ...
- python语法区别
python语法区别: 大小写敏感 (动态语言:python)变量不用声明 p.s: 静态语言(Java)必须声明变量 语句末尾可以不打分号 可以直接进行数学计算 复制.粘贴功能失效,粘贴到别的地方的 ...
- Html学习之一(锚点链接的使用,页面间的跳转)
页面一: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- day79_10_28git使用基础
一.git与svn比较. git就是版本控制器,控制的对象是开发的项目代码. 可以根具时间轴进行回滚代码,改变代码版本. svn的特点就是服务版与用户版分离,当开发这需要进行开发时,需要先在代码仓库中 ...
- arduino控制A9G发送短信
#include<SoftwareSerial.h> #define phonenum_call "18150561160" // 最好移动卡 联通卡支持度不是很好 S ...
- hdu6468 dfs剪枝 or char数组 or 构造
http://acm.hdu.edu.cn/showproblem.php?pid=6468 题意 有一个序列,是1到n的一种排列,排列的顺序是字典序小的在前,那么第k个数字是什么?(\(1 \leq ...