javascript闭包传参和事件的循环绑定示例探讨


Posted in Javascript onApril 17, 2014

今天看到一个javascript的题目,按常理循环绑定事件,但是得到的结果却不是想要的。

<a href="#">text</a> 
<br> 
<a href="#">link</a> 
<script> 
var as = document.getElementsByTagName('a'); 
for ( var i = as.length; i--; ) { 
as[i].onclick = function() { 
alert(i); 
return false; 
} 
} 
</script>

1.这个代码点击链接弹出的i都是-1,这是为啥呢?

简单来说就是函数变量作用域问题,如果把function() { alert(i); return false; } 当做一个函数 a();a()内部未定义变量i,但是内部使用了,于是向外查找,找到for循环里定义的i,点击事件是for循环完毕后才开始执行的,执行完毕后i的值已经变成-1;所以每次弹出的都是-1;

2. 2个参数的for循环也不常见!疑惑?

for(语句1,语句2,语句3){

//todo

}

a.for循环条件

通常说语句1、语句2、语句3都是可选的。

b.语句 2:

通常语句 2 用于评估初始变量的条件。

语句 2 同样是可选的。

如果语句 2 返回 true,则循环再次开始,如果返回 false,则循环将结束。

提示:如果您省略了语句 2,那么必须在循环内提供 break。否则循环就无法停下来。这样有可能令浏览器崩溃。

c.关于 i--判断:

判断i--true /false的时候是先判断i再运算i--的。进入最后一次判断 i--的时候其实判断 i==0的时候,判断后又执行了一次i--,for循环终止, 于是i的值变成了-1;

var i = 1;

!!i--;//ture

解决方法:

var as = document.getElementsByTagName('a'); 
for ( var i = as.length; i--; ) { 
(function(i){ 
as[i].onclick = function() { 
alert(i); 
return false; 
} 
})(i) 
}

或者:
var as = document.getElementsByTagName('a'); 
for ( var i = as.length; i--; ) { 
var a = function(i){ 
as[i].onclick = function() { 
alert(i); 
return false; 
} 
} 
a(i); 
}

其他网友7中解决方法demo:
<html > 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>闭包演示</title> 
<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>产品一</p> 
<p>产品二</p> 
<p>产品三</p> 
<p>产品四</p> 
<p>产品五</p> 
</body> 
</html>

1、将变量 i 保存给在每个段落对象(p)上
function init() { 
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 保存在匿名函数自身
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以函数参数形式传递给内层函数
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以局部变量形式传递给内存函数
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的细微区别)
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实现,实际上每产生一个函数实例就会产生一个闭包
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的区别
function init7() { 
var pAry = document.getElementsByTagName("p"); 
for( var i=0; i<pAry.length; i++ ) { 
pAry[i].onclick = Function('alert('+i+')') 
} 
}

总结完成,欢迎拍砖!
Javascript 相关文章推荐
Javascript的时间戳和php的时间戳转换注意事项
Apr 12 Javascript
javascript实现3D变换的立体圆圈实例
Aug 06 Javascript
JavaScript中数组的合并以及排序实现示例
Oct 24 Javascript
js中常用的Tab切换效果(推荐)
Aug 30 Javascript
jQuery属性选择器用法示例
Sep 09 Javascript
JS小数转换为整数的方法分析
Jan 07 Javascript
详解网站中图片日常使用以及优化手法
Jan 09 Javascript
EasyUi 打开对话框后控件赋值及赋值后不显示的问题解决办法
Jan 19 Javascript
vue.js异步上传文件前后端实现代码
Aug 22 Javascript
js数组常用最重要的方法
Feb 04 Javascript
利用jqgrid实现上移下移单元格功能
Nov 07 Javascript
js+canvas实现画板功能
Sep 13 Javascript
window.location不跳转的问题解决方法
Apr 17 #Javascript
JavaScript避免代码的重复执行经验技巧分享
Apr 17 #Javascript
js中的cookie的读写操作示例详解
Apr 17 #Javascript
巧用replace将文字表情替换为图片
Apr 17 #Javascript
JavaScript事件委托的技术原理探讨示例
Apr 17 #Javascript
JS实现div居中示例
Apr 17 #Javascript
淘宝网提供的国内NPM镜像简介和使用方法
Apr 17 #Javascript
You might like
php二维数组排序方法(array_multisort usort)
2013/12/25 PHP
thinkphp连贯操作实例分析
2014/11/22 PHP
PHP列出MySQL中所有数据库的方法
2015/03/12 PHP
实现PHP中session存储及删除变量
2018/10/15 PHP
php多进程应用场景实例详解
2019/07/22 PHP
php中文语义分析实现方法示例
2019/09/28 PHP
Extjs 继承Ext.data.Store不起作用原因分析及解决
2013/04/15 Javascript
可自定义速度的js图片无缝滚动示例分享
2014/01/20 Javascript
js调用后台、后台调用前台等方法总结
2014/04/17 Javascript
javascript浏览器兼容教程之事件处理
2014/06/09 Javascript
使用impress.js制作幻灯片
2015/09/09 Javascript
原生js实现autocomplete插件
2016/04/14 Javascript
JavaScript实现鼠标点击导航栏变色特效
2017/02/08 Javascript
JavaScript数据结构之二叉查找树的定义与表示方法
2017/04/12 Javascript
vue  directive定义全局和局部指令及指令简写
2018/11/20 Javascript
vue监听dom大小改变案例
2020/07/29 Javascript
jquery实现异步文件上传ajaxfileupload.js
2020/10/23 jQuery
Python中利用sorted()函数排序的简单教程
2015/04/27 Python
在Python中编写数据库模块的教程
2015/04/29 Python
使用简单工厂模式来进行Python的设计模式编程
2016/03/01 Python
python使用电子邮件模块smtplib的方法
2016/08/28 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
2018/06/05 Python
推荐10款最受Python开发者欢迎的Python IDE
2018/09/16 Python
pytorch 状态字典:state_dict使用详解
2020/01/17 Python
Python基于requests实现模拟上传文件
2020/04/21 Python
Html5游戏开发之乒乓Ping Pong游戏示例(一)
2013/01/21 HTML / CSS
基于HTML5新特性Mutation Observer实现编辑器的撤销和回退操作
2016/01/11 HTML / CSS
详解px单位html5响应式方案
2018/03/08 HTML / CSS
圣彼得堡鲜花配送:Semicvetic
2020/09/15 全球购物
如何减少垃圾回收让内存更加有效使用
2013/10/18 面试题
C# .NET面试题
2015/11/28 面试题
出生公证书样本
2014/04/04 职场文书
环保口号大全
2014/06/12 职场文书
2015年暑假工作总结
2015/07/13 职场文书
redis通过6379端口无法连接服务器(redis-server.exe闪退)
2021/05/08 Redis
Python通过loop.run_in_executor执行同步代码 同步变为异步
2022/04/11 Python