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对象的property属性详解
Apr 01 Javascript
JavaScript给按钮绑定点击事件(onclick)的方法
Apr 07 Javascript
javascript实现计时器的简单方法
Feb 21 Javascript
JavaScript调试之console.log调试的一个小技巧分享
Aug 07 Javascript
vue 里面使用axios 和封装的示例代码
Sep 01 Javascript
js传递数组参数到后台controller的方法
Mar 29 Javascript
详解webpack 打包文件体积过大解决方案(code splitting)
Apr 10 Javascript
简述vue状态管理模式之vuex
Aug 29 Javascript
微信小程序冒泡事件及其阻止方法实例分析
Dec 06 Javascript
ES6 Symbol数据类型的应用实例分析
Jun 26 Javascript
微信小程序利用button控制条件标签的变量问题
Mar 15 Javascript
Vue实现Layui的集成方法步骤
Apr 10 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调用三种数据库的方法(2)
2006/10/09 PHP
Ext.data.PagingMemoryProxy分页一次性读取数据的实现代码
2010/04/07 PHP
mac环境中使用brew安装php5.5.15
2014/08/18 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
不错的asp中显示新闻的功能
2006/10/13 Javascript
js身份证验证超强脚本
2008/10/26 Javascript
jQuery获取CSS样式中的颜色值的问题,不同浏览器格式不同的解决办法
2013/05/13 Javascript
Js注册协议倒计时的小例子
2013/06/24 Javascript
JS+CSS实现简易实用的滑动门菜单效果
2015/09/18 Javascript
BootStrap制作导航条实例代码
2016/05/06 Javascript
AngularJS ng-mousedown 指令
2016/08/02 Javascript
JS声明式函数与赋值式函数实例分析
2016/12/13 Javascript
Bootstrap如何激活导航状态
2017/03/22 Javascript
vue2.0实现倒计时的插件(时间戳 刷新 跳转 都不影响)
2017/03/30 Javascript
JavaScript数据结构之双向链表和双向循环链表的实现
2017/11/28 Javascript
红黑树的插入详解及Javascript实现方法示例
2018/03/26 Javascript
jQuery中each遍历的三种方法实例分析
2018/09/07 jQuery
从0到1搭建Element的后台框架的方法步骤
2019/04/10 Javascript
一些手写JavaScript常用的函数汇总
2019/04/16 Javascript
详解Python中的正则表达式的用法
2015/04/09 Python
Python程序员面试题 你必须提前准备!
2018/01/16 Python
python opencv之分水岭算法示例
2018/02/24 Python
使用Python实现文字转语音并生成wav文件的例子
2019/08/08 Python
pytorch numpy list类型之间的相互转换实例
2019/08/18 Python
css3的transition属性详解
2014/12/15 HTML / CSS
Europcar英国:英国汽车和货车租赁
2017/01/21 全球购物
波兰数码相机及配件网上商店: Cyfrowe.pl
2017/06/19 全球购物
英国定做窗帘和纺织品面料一站式商店:Dekoria
2018/08/29 全球购物
Stuarts London美国/加拿大:世界领先的独立男装零售商之一
2019/03/18 全球购物
如果重写了对象的equals()方法,需要考虑什么
2014/11/02 面试题
教师党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
检讨书模板
2015/01/29 职场文书
施工单位工程部经理岗位职责
2015/04/09 职场文书
情况说明书怎么写
2015/10/08 职场文书
妇联2016年六一国际儿童节活动总结
2016/04/06 职场文书
Python实现简单的猜单词
2021/06/15 Python