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 相关文章推荐
很全的显示阴历(农历)日期的js代码
Jan 01 Javascript
js清除input中type等于file的值域(示例代码)
Dec 24 Javascript
用jquery实现的一个超级简单的下拉菜单
May 18 Javascript
jQuery与Ajax以及序列化
Feb 01 Javascript
初识angular框架后的所思所想
Feb 19 Javascript
基于BootStrap Metronic开发框架经验小结【九】实现Web页面内容的打印预览和保存操作
May 12 Javascript
基于jQuery实现的Ajax 验证用户名唯一性实例代码
Jun 28 jQuery
javascript回调函数详解
Feb 06 Javascript
详解JavaScript中typeof与instanceof用法
Oct 24 Javascript
Vue多环境代理配置方法思路详解
Jun 21 Javascript
js+css3实现简单时钟特效
Sep 13 Javascript
vue操作dom元素的3种方法示例
Sep 20 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调用三种数据库的方法(1)
2006/10/09 PHP
php empty函数 使用说明
2009/08/10 PHP
php 上传功能实例代码
2010/04/13 PHP
PHP实现的简单日历类
2014/11/29 PHP
PHP使用内置函数file_put_contents写入文件及追加内容的方法
2015/12/07 PHP
PHP设计模式之迭代器模式
2016/06/17 PHP
php利用ZipArchive类操作文件的实例
2020/01/21 PHP
关于js注册事件的常用方法
2013/04/03 Javascript
利用Angular.js限制textarea输入的字数
2016/10/20 Javascript
使用JSON作为函数的参数的优缺点
2016/10/27 Javascript
EasyUI Combobox设置默认值 获取text的方法
2016/11/28 Javascript
Bootstrap基本组件学习笔记之面板(14)
2016/12/08 Javascript
Node.js学习入门
2017/01/03 Javascript
javascript 秒表计时器实现代码
2017/03/09 Javascript
从零开始做一个pagination分页组件
2017/03/15 Javascript
validationEngine 表单验证插件使用实例代码
2017/06/15 Javascript
webpack学习--webpack经典7分钟入门教程
2017/06/28 Javascript
详解Vue SSR( Vue2 + Koa2 + Webpack4)配置指南
2018/11/13 Javascript
使用rollup打包JS的方法步骤
2018/12/05 Javascript
vue设置导航栏、侧边栏为公共页面的例子
2019/11/01 Javascript
Vue实现按钮级权限方案
2019/11/21 Javascript
如何手写一个简易的 Vuex
2020/10/10 Javascript
Vue中ref和$refs的介绍以及使用方法示例
2021/01/11 Vue.js
在Django中创建URLconf相关的通用视图的方法
2015/07/20 Python
python 垃圾收集机制的实例详解
2017/08/20 Python
Python设计模式之观察者模式原理与用法详解
2019/01/16 Python
Python实现新型冠状病毒传播模型及预测代码实例
2020/02/05 Python
Python 改变数组类型为uint8的实现
2020/04/09 Python
纯CSS3实现地球自转实现代码(图文教程附送源码)
2012/12/26 HTML / CSS
HTML5新增的表单元素和属性实例解析
2014/07/07 HTML / CSS
澳洲小众品牌的集合网站:BNKR
2018/02/23 全球购物
Sneaker Studio捷克:购买运动鞋
2018/07/08 全球购物
中学生期末评语
2014/02/03 职场文书
高中语文课后反思
2014/04/27 职场文书
学生评语集锦
2015/01/04 职场文书
MySQL新手入门进阶语句汇总
2022/09/23 MySQL