今天看到一个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闭包传参和事件的循环绑定的更多相关文章

  1. javascript闭包传参就这么简单

    var query = (function (a) { return a; })('fx'); alert(query);

  2. 闭包传参 余额计算 钩子hook 闭包中的this JavaScript 钩子

    闭包传参  余额计算    钩子hook 小程序 a=function(e){console.log(this)}() a=function(e){console.log(this)}() VM289 ...

  3. webpack+vue 组件间传参(单一事件中心管理组件通信--$root),如果有路由的话会失效

    先给一个例子: <body> <div id="box"> <com-a></com-a> <com-b></co ...

  4. elementUi中的计数器ele-mumber中的change事件传参及事件调用

    业务场景是需要在点击业务工作量的时候设置任务工作量这一项的评分不能大于任务质量及任务时限的权重之和除以二 上代码 JS逻辑代码 因出现弹出层提示后设置输入框的值如果大于sum的值,设置输入的值为sum ...

  5. Javascript 函数传参问题

    属于传值,不能改变参数的属性 example 1  function Myvalue(){ var arry = 5; return arry ; } document.getElementById( ...

  6. 从一道面试题分析javascript闭包

    据说是一不注意就会做错的五道javascript面试题之一,我们来看看这道题长什么样 function Container( properties ) { var objthis = this; fo ...

  7. C# 线程传参

    传参方式有两种: 1.创建带参构造方法类 传参 2.利用Thread.start(8)直接传参,该方法会接收一个对象,并将该对象传递给线程,因此在线程中启动的方法 必须接收object类型的单个参数. ...

  8. 【WPF】CommandParameter解决多传参问题

    方法一:传参按钮控件自身绑定的ItemSource 用WAF框架实现MVVM,按钮的点击事件都要通过Command来传递到这个View对应的ViewModel上,再通过ViewModel传递到上层的C ...

  9. react-绑定this并传参的三种方式

    绑定this并传参的三种方式 在事件中绑定this并传参: <input type="button" value="在事件中绑定this并传参" onCl ...

随机推荐

  1. UIView frame, bounds and center

    http://stackoverflow.com/questions/5361369/uiview-frame-bounds-and-center Since the question I asked ...

  2. Hadoop: the definitive guide 第三版 拾遗 第十二章 之Hive初步

    Hive简介 Hive是建立在 Hadoop 上的数据仓库基础构架.它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储.查询和分析存储在 Hadoop 中的大规模数据的机制 ...

  3. LigerUi中的Grid中不分页显示(local)!

    LigerUi中的Grid中不分页显示! grid为local usePager: true,                         //是否分页

  4. Android学习(一)

    #常见布局 ###线性布局 有一个布局方向,水平或者竖直 在竖直布局下,左对齐.右对齐,水平居中生效 在水平布局下,顶部对齐.底部对齐.竖直居中生效 权重:按比例分配屏幕的剩余宽度或者高度 ###相对 ...

  5. ActiveForm

    ActiveForm要和Model一起使用 我想在你的控制器的action中,至少应该这么写: /*action*/ $model = new Comments(); //实例化 Comments m ...

  6. 黑马程序猿——Java中的类载入器

    ------- android培训.java培训.期待与您交流! -------- 类载入器 Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器,每一个类负责载入特定位置的类: BootS ...

  7. 【HDU 2014 Multi-University Training Contest 1 1002】/【HDU 4862】Jump

    多校训练就这么华丽丽的到了 ,于是乎各种华丽丽的被虐也開始了. 这是多校的1002; 最小费用最大流. 题目大意: 有n*m个方格,每一个方格都一个的十进制一位的数.你能够操作K次. 对于每一次操作, ...

  8. 苹果电脑出现 .DS_Store文件,删除不掉怎么处理?

    今天早上打开电脑,发现桌面上出现一个.DS_Store文件.可是出现的莫名其妙,也就没在意,可是重复删除之后还是出现.后来查了一下网上的资料,才知道,昨天我加入git的时候,为了看见 .git这个隐藏 ...

  9. 启动MYSQL密码审计插件

    http://www.innomysql.com/article/25717.html [root@server-mysql plugin]# pwd /usr/local/mysql56/lib/p ...

  10. lambda与函数调用的转换

    14.38 编写一个类令其检查某个给定的string对象的长度是否与一个阈值相等.使用该对象编写程序,统计并报告在输入的文件中长度为1的单词有多少个,长度为2的单词有多少个.......长度为10的单 ...