利用闭包解决for循环里onclick事件不能捕捉实时i值问题
问题描述
我们都知道,如果我们对于一组元素(相同的标签)同时进行onclick事件处理的时候(在需要获取到索引的时候),一般是写一个for循环,但是onclick是一个异步调用的,所以会带来一个问题,当我们触发这个事件的时候,我们能获取的i值是for完整执行完后i的值,而不能获取到代码顺序里i的值
首先看一段代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button>0</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<script>
var btn=document.getElementsByTagName('button');
for(var i=0;i<btn.length;i++){
btn[i].onclick=function(){
console.log(i);
}
}
</script>
</body>
</html>
然后运行一下,当时作为一名天真的js初学者理所当然的认为分别点击不同的额按钮,会分别的打印出0、1、2、3、4,然而事与愿为,现实和理想总是存在差距,点击不同的按钮,打印却都是5,百思不得其解,不科学啊! 最后百度了一番才恍然大悟,原来console.log(i)里的i在循环完成的时候被赋值成了5,而每个按钮的onclick都被赋值了同一个function,也就是说每个function里的i指的是同一个i,i=5,自然每个点击都会打印出5,那么该怎么解决呢?!
利用闭包解决
再看接下来这段代码:
<script>
var btn=document.getElementsByTagName('button');
for(var i=0;i<btn.length;i++){
(function(n){ //这个是function里n,即function的形参,也可以换成j,换成什么变量名都无所谓
btn[n].onclick=function(){
console.log(i+'-'+n); //i总是等于5,而n则是点击的数
}
})(i);//这是循环中的i,被作为参数传入
}
</script>
再运行这段代码,就可以得到你想要的效果,但是是为什么呢? 知道了原因就好办了,利用闭包把每个function里的i都变成不同的i就行了,当时作为一名初学者还不懂闭包,也是后来才理解的。 循环中的function自调用,将循环中的i作为参数传入function中,此时,function中的i已经不是循环中的i了(这里有点绕,其实形参i,即function里的i换成什么变量名都行),而是在内存中开辟了一个内存空间存储了作为参数传进来的i的值,这样function中的就不会随着循环中的i的值的改变而改变了,就可以打印出你要的结果了。
原理:
闭包的局部作用域。由于这个你们函数总是和代码执行顺序一样的,所以n可以实时记录i的值。由于for每执行一次,就执行一次匿名函数,每一次执行有自己的执行环境,有着自己的作用域链,所以用这函数里面一个变量来记录一下实时的i的值,这个n是不会随着i的改变而改变的
- 通过 JS 判断页面是否有滚动条的简单方法
- Log4j官方文档翻译(六、日志的级别)
- AngularJS API之isXXX()
- 《linux c编程指南》学习手记4
- Kibana中doc与search策略的区别
- jQuery 图片查看插件 Magnify 开发简介(仿 Windows 照片查看器)
- Log4j官方文档翻译(五、日志输出的方法)
- AngularJS API之copy深拷贝
- 光标定位,隐藏光标
- AngularJS API之toJson 对象转为JSON
- Log4j官方文档翻译(七、日志格式化)
- Log4j官方文档翻译(八、文件输出)
- 《linux c编程指南》学习手记3
- Log4j官方文档翻译(九、输出到数据库)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法