Javascript闭包演示【转】
文章出自http://www.cnblogs.com/snandy/archive/2011/03/01/1967628.html
有个网友问了个问题,如下的html,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<!DOCTYPE HTML> <html> <head> <meta charset= "utf-8" /> <title>闭包演示</title> <style type= "text/css" > p {background:gold;} </style> <script type= "text/javascript" > function init() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { pAry[i].onclick = function () { alert(i); } } } </script> </head> <body onload= "init();" > <p>产品 0</p> <p>产品 1</p> <p>产品 2</p> <p>产品 3</p> <p>产品 4</p> </body> </html> |
以上场景是初学者经常碰到的。即获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。
原因是初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。
了解了原因,摸索出了很多解决办法(纯粹是兴趣)。最先想到的前两种
1、将变量 i 保存给在每个段落对象(p)上
1
2
3
4
5
6
7
8
9
|
function init1() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { pAry[i].i = i; pAry[i].onclick = function () { alert( this .i); } } } |
2、将变量 i 保存在匿名函数自身
1
2
3
4
5
6
7
8
|
function init2() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { (pAry[i].onclick = function () { alert(arguments.callee.i); }).i = i; } } |
后又想到了三种
3、加一层闭包,i 以函数参数形式传递给内层函数
1
2
3
4
5
6
7
8
9
10
|
function init3() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { ( function (arg){ pAry[i].onclick = function () { alert(arg); }; })(i); //调用时参数 } } |
4、加一层闭包,i 以局部变量形式传递给内层函数
1
2
3
4
5
6
7
8
9
10
11
|
function init4() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { ( function () { var temp = i; //调用时局部变量 pAry[i].onclick = function () { alert(temp); } })(); } } |
5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)
1
2
3
4
5
6
7
8
9
10
|
function init5() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { pAry[i].onclick = function (arg) { return function () { //返回一个函数 alert(arg); } }(i); } } |
后又发现了两种
6、用Function实现,实际上每产生一个函数实例就会产生一个闭包
1
2
3
4
5
6
|
function init6() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { pAry[i].onclick = new Function( "alert(" + i + ");" ); //new一次就产生一个函数实例 } } |
7、用Function实现,注意与6的区别
1
2
3
4
5
6
|
function init7() { var pAry = document.getElementsByTagName( "p" ); for ( var i=0; i<pAry.length; i++ ) { pAry[i].onclick = Function( 'alert(' +i+ ')' ); } } |
Javascript闭包演示【转】的更多相关文章
- JavaScript闭包演示
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8" /> <title&g ...
- js闭包演示
有个网友问了个问题,如下的html,为什么每次输出都是5 <html > <head> <meta http-equiv="Content-Type" ...
- JavaScript闭包模型
JavaScript闭包模型 ----- [原创翻译]2016-09-01 09:32:22 < 一> 闭包并不神秘 本文利用JavaScript代码来阐述闭包,目的是为了使普通 ...
- JavaScript闭包示例
在下面的例子中,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4. <html> <head> <meta charset="utf ...
- javascript闭包传参和事件的循环绑定
今天看到一个javascript的题目,按常理循环绑定事件,但是得到的结果却不是想要的. <a href="#">text</a><br>< ...
- JavaScript 闭包环境非常奇特 - 相当于类与实例的关系?!
JavaScript 闭包环境非常奇特 - 相当于类与实例的关系?! 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一 ...
- 让你能看懂的 JavaScript 闭包
让你能看懂的 JavaScript 闭包 没有废话,直入主题,先看一段代码: var counter = (function() { var x = 1; return function() { re ...
- Javascript闭包入门(译文)
前言 总括 :这篇文章使用有效的javascript代码向程序员们解释了闭包,大牛和功能型程序员请自行忽略. 译者 :文章写在2006年,可直到翻译的21小时之前作者还在完善这篇文章,在Stackov ...
- javascript闭包中循环问题
如下的html,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5. <html > <head> <meta http-equiv=&quo ...
随机推荐
- SQLMAP使用详解
使用示例 python sqlmap.py -u "http://xx.com/member.php?id=XX" -p id --dbms "Mysql" ...
- vue调用豆瓣API加载图片403问题
"豆瓣API是有请求次数限制的”,这会引发图片在加载的时候出现403问题,视图表现为“图片加载不出来”,控制台表现为报错403. 其实是豆瓣限制了图片的加载,我自己用了一个办法把图片缓存下来 ...
- 大数据学习--day02(标识符、变量、数据类型、类型转换、进制转换、原码反码补码)
标识符.变量.数据类型.类型转换.进制转换.原码反码补码 标识符: java50个关键字不能做标识符,以数字开头不能做标识符(这个老是忘记写一个类名的时候) 变量: 变量分为成员变量和局部变量,注意作 ...
- ElasticSearch5插件安装
http://blog.csdn.net/napoay/article/details/53896348 #更新 sudo yum update -y sudo rpm -ivh http://dl. ...
- 内网环境下为Elasticsearch 5.0.2 添加head服务
背景: 本项目的服务器是内网环境,没有网络,因此需要在离线的环境中,安装head服务. 需要用到的安装包有: node的安装包 elasticsearch的head插件源码 说明:此次只讲述为elas ...
- 浅谈ETL架构中ODS的作用以及如何在HaoheDI中自动创建ODS表
什么是ODS表? 在ETL架构中,源数据很少会直接抽取加载到数据仓库EDW,二者之间往往会设置一个源数据的临时存储区域,存储数据在清洗转换前的原始形态,通常被大家称做操作型数据存储,简称ODS,在Ki ...
- 利用haohedi ETL将数据库中的数据抽取到hadoop Hive中
采用HIVE自带的apache 的JDBC驱动导入数据基本上只能采用Load data命令将文本文件导入,采用INSERT ... VALUES的方式插入速度极其慢,插入一条需要几十秒钟,基本上不可用 ...
- C语言中字符串赋值的几个理解
在C语言中,字符串的赋值主要有两种方法,第一种是通过指针的方式直接赋值,第二种是通过数组直接赋值. 一.首先,我们来看第一种赋值方法:指针式赋值 我们知道,上面的示例是显然可以正常执行的,也是很容易理 ...
- 第二节 双向链表的GO语言实现
一.什么是双向链表 和单链表比较,双向链表的元素不但知道自己的下线,还知道自己的上线(越来越像传销组织了).小煤车开起来,图里面可以看出,每个车厢除了一个指向后面车厢的箭头外,还有一个指向前面车厢的箭 ...
- 解决区间第K大的问题的各种方法
例题:http://poj.org/problem?id=2104 最近可能是念念不忘,必有回响吧,总是看到区间第k大的问题,第一次看到是在知乎上有人面试被弄懵了后来又多次在比赛中看到.以前大概是知道 ...