由于js词法性质和全局变量被更改,循环绑定的click事件执行时变量和定义时 不一致的bug,各种解决方案。

动态在页面上添加了5个按钮,实现的功能应该是点击对应按钮在控制台输出相应的索引。但因为应该是i的变量应该一直指引的对应的地址,所以一直输出的是5.就是想请教您一下,这种问题应该是怎么样的一个解决思路。您要是有时间的时候帮我看下。非常感谢!

问题:

 //这个有bug,一直输出5
for (var i =0 ; i<5 ; i++){
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Button"+i));
btn.addEventListener("click",function(){
console.log(i);
});
document.body.appendChild(btn);
}

错误解法一:

(虽然定义了新变量 ,避免了使用全局的i,但是,新变量一直被重新定义,最终定义为和最新的i保持一样了 )

     for (var i =0 ; i<5 ; i++){
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Button"+i));var j=i;
btn.addEventListener("click",function(){
console.log(j);
});
document.body.appendChild(btn);
} //一直输出4

错误解法二:

(所谓闭包)

 for (var i =0 ; i<5 ; i++){
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Button"+i));
btn.addEventListener("click",function(){
var result = function (num){
return function(){
return num;
}
}(i);
console.log(result);
}
);
document.body.appendChild(btn);
}
解决方法一:
 for (var i =0 ; i<5 ; i++){
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Button"+i));
btn.id="btn_"+i;
btn.addEventListener("click",function(){
console.log(this.id.split("_")[1]);
});
document.body.appendChild(btn);
}

解决方法二:

     for (var i =0 ; i<5 ; i++){
var btn = document.createElement("button");
!function(i){
btn.appendChild(document.createTextNode("Button"+i));
btn.addEventListener("click",function(){
console.log(i);
});
}(i);
document.body.appendChild(btn);
}
 1     for (var i =0 ; i<5 ; i++){
2 var btn = document.createElement("button");
3 (function(i){
4 btn.appendChild(document.createTextNode("Button"+i));
5 btn.addEventListener("click",function(){
6 console.log(i);
7 });
8 })(i);
9 document.body.appendChild(btn);
10 }

 总结:

 两种闭包方案,为何一个错,一个对?

 虽然都是闭包,但是你的没有把需要的东西给关闭进去,因为你的范围太小,你关时,人家已经是5 了。

 
两种正确做法有何区别?
而他们的写法是,在没成5时,就关闭进去,这样就保护了变量的中间值,他们存在闭包内,而另一种存在dom上,异曲同工之妙,都达到了中间值的保存。
 

由于js词法性质和全局变量被更改,循环绑定的click事件执行时变量和定义时 不一致的bug,各种解决方案。的更多相关文章

  1. (转载)js(jquery)的on绑定点击事件执行两次的解决办法

    js(jquery)的on绑定点击事件执行两次的解决办法—不是事件绑定而是事件冒泡 遇到的问题:jquery中用.on()给页面中新加的元素添加点击事件时,点击事件源,绑定的事件执行两次,这里的ale ...

  2. JS如何给ul下的所有li绑定点击事件,点击使其弹出下标和内容

    这是一个非常常见的面试题,出题方式多样,但考察点相同,下面我们来看看这几种方法:方法一: var itemli = document.getElementsByTagName("li&quo ...

  3. JS流程控制语句 重复重复(for循环)语句结构: for(初始化变量;循环条件;循环迭代) { 循环语句 }

    重复重复(for循环) 很多事情不只是做一次,要重复做.如打印10份试卷,每次打印一份,重复这个动作,直到打印完成.这些事情,我们使用循环语句来完成,循环语句,就是重复执行一段代码. for语句结构: ...

  4. JS CKEditor使用setData后绑定click事件

    CKEditor使用setData()时会自动丢失初始时绑定的时间,在百度时发现有很多方法都不对. 近期在做项目的时候,由于客户需要,将原来的文本格式的textarea标签更改成富文本编辑器--CKE ...

  5. jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行?

    jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行? 因为在解析时最新解析的就是JA ...

  6. js使用心得——避免全局变量冲突的小技巧

    在写js代码的时候,经常会因为这样或者那样的原因用到全局变量,如果全局变量只在一个js里使用,那就没问题,但如果变量在不同的js文件里出现,这时隐藏的问题就会开始暴露,也许你能很快修复出现的BUG,又 ...

  7. js词法作用域规则

    function foo() {console.log( a ); // 2不是3} function bar() {var a = 3;foo();} var a = 2;bar(); js中的作用 ...

  8. JS中如何生成全局变量

    JS中如何生成全局变量 一.总结 一句话总结:在函数内部,一般用var声明的为局部变量,没用var声明的一般为全局变量 在函数内没用var声明的一般为全局变量 1.js中的函数中的this指向的是谁? ...

  9. 对js中局部变量、全局变量和闭包的理解

    对js中局部变量.全局变量和闭包的理解 局部变量 对于局部变量,js给出的定义是这样的:在 JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它.(该变量的作用域 ...

随机推荐

  1. P2759 奇怪的函数

    题目描述 使得 x^x 达到或超过 n 位数字的最小正整数 x 是多少? 输入输出格式 输入格式: 一个正整数 n 输出格式: 使得 x^x 达到 n 位数字的最小正整数 x 输入输出样例 输入样例# ...

  2. zabbix snmp、jmx配置使用

    SNMP: snmp是很古老的监控,我萌几乎可以在所有设备上看到它的身影 [root@linux-node1 ~]# yum install net-snmp net-snmp-libs net-sn ...

  3. 【222】◀▶ IDL 输入输出函数说明

    参考:I/O - General Input/Output Routines —— 基本输入输出函数 01   PRINT/PRINTF 格式化输出. 02   READ/READF 格式化输入. 0 ...

  4. 量子隐形传态1 Quantum Teleportation

    量子隐形传态是量子纠缠的又一个应用. 隐形传态,所谓隐形的意思就是没有物质介质就传递了信息,在经典世界,传递信息要有介质,光.电磁波或者其他的什么,但是在量子的世界里,我可以把信息传递给你,并且不传递 ...

  5. CodeForces 1098E. Fedya the Potter

    题目简述:给定长度为$n \leq 5\times 10^4$的序列$a_1, a_2, \dots, a_n \leq 10^5$.将$\gcd(a_l, a_{l+1}, \dots, a_r) ...

  6. c++函数模板二栈实现

    1 没有使用模板的栈实现 #include <iostream> #include <string> using namespace std; class Stack { pu ...

  7. Ubuntu 下编译libjingle-0.6.14 (转载)

    转自:http://blog.csdn.net/feifei454498130/article/details/8197103 添加依赖库: sudo apt-get install build-es ...

  8. vuex实现购物车功能

    购物车功能描述: 1. 点击+,-按钮,“已选:xx件”随之增减 2. checkbox选中时,当前项的已选数量增加到头部“已选择xx件”中,未选中时数量不计入 代码: 服务端 node+koa+ko ...

  9. Lightoj1012【DFS】

    题意: 输出和' @ '相连有多少个' . '包括' @ ',' # '代表墙不能走: 思路: 基础DFS,找到起点,然后跑一下DFS就好了: #include<cstdio> #incl ...

  10. bzoj 2395: [Balkan 2011]Timeismoney【计算几何+最小生成树】

    妙啊,是一个逼近(?)的做法 把两个值最为平面上的点坐标,然后答案也是一个点. 首先求出可能是答案的点xy分别是按照c和t排序做最小生成树的答案,然后考虑比这两个点的答案小的答案,一定在xy连线靠近原 ...