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 相关文章推荐
event.srcElement+表格应用
Aug 29 Javascript
In Javascript Class, how to call the prototype method.(three method)
Jan 09 Javascript
Javascript valueOf 使用方法
Dec 28 Javascript
细品javascript 寻址,闭包,对象模型和相关问题
Apr 27 Javascript
JS 日期比较大小的简单实例
Jan 13 Javascript
使用jQuery时Form表单元素ID和name命名大忌
Mar 06 Javascript
javascript 实现map集合
Apr 03 Javascript
AngularJs Managing Service Dependencies详解
Sep 02 Javascript
React中ES5与ES6写法的区别总结
Apr 21 Javascript
详解Vue学习笔记进阶篇之列表过渡及其他
Jul 17 Javascript
vscode中vue-cli项目es-lint的配置方法
Jul 30 Javascript
vue实现新闻展示页的步骤详解
Apr 11 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编实现程动态图像的创建代码
2008/09/28 PHP
Mac版PhpStorm之XAMPP整合apache服务器配置的图文教程详解
2016/10/13 PHP
浅谈php调用python文件
2019/03/29 PHP
JavaScript 定义function的三种方式小结
2009/10/16 Javascript
jQuery的三种$()
2009/12/30 Javascript
那些年,我还在学习jquery 学习笔记
2012/03/05 Javascript
js遍历、动态的添加数据的小例子
2013/06/22 Javascript
js中substr,substring,indexOf,lastIndexOf的用法小结
2013/12/27 Javascript
Seajs 简易文档 提供简单、极致的模块化开发体验
2016/04/13 Javascript
Bootstrap框架的学习教程详解(二)
2016/10/18 Javascript
jQuery实现背景滑动菜单
2016/12/02 Javascript
10个经典的网页鼠标特效代码
2018/01/09 Javascript
Nuxt.js踩坑总结分享
2018/01/18 Javascript
Webpack4+Babel7+ES6兼容IE8的实现
2019/04/10 Javascript
浅入深出Vue之组件使用
2019/07/11 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
2020/05/25 Javascript
Vue 3.0中jsx语法的使用
2020/11/13 Javascript
vue 插槽简介及使用示例
2020/11/19 Vue.js
python中wx将图标显示在右下角的脚本代码
2013/03/08 Python
tensorflow 保存模型和取出中间权重例子
2020/01/24 Python
你需要学会的8个Python列表技巧
2020/06/24 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
美国瑜伽品牌:Gaiam
2017/10/31 全球购物
奥地利票务门户网站:oeticket.com
2019/12/31 全球购物
全球烹饪课程的领先预订平台:Cookly
2020/01/28 全球购物
如何设定的weblogic的热启动模式(开发模式)与产品发布模式
2012/09/08 面试题
建筑设计学生的自我评价
2014/01/16 职场文书
演讲稿的写法
2014/05/19 职场文书
党支部特色活动方案
2014/08/20 职场文书
创先争优宣传标语
2014/10/08 职场文书
小学少先队辅导员述职报告
2015/01/10 职场文书
学校2016年圣诞节活动总结
2016/03/31 职场文书
pytorch中Schedule与warmup_steps的用法说明
2021/05/24 Python
Redis可视化客户端小结
2021/06/10 Redis
浅谈Python中的正则表达式
2021/06/28 Python
python在package下继续嵌套一个package
2022/04/14 Python