for 循环中的 i 变量问题
1:如何点击每一个 li 的时候 alert 输出其index?
<ul id="test">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
window.onload = function(){
var oLis = document.getElementById("test").getElementsByTagName("li");
for(var i = 0;i < oLis.length;i ++){
oLis[i].onclick = function(){
alert(i); //每次都是4
}
}
}
解析:因为在for循环里面指定给oLis[i].onclick的事件处理程序,也就是onclick那个匿名函数是在for循环执行完成后(用户点击时)才被调用的。而调用时,需要对变量i求值,解析程序首先会在事件处理程序内部查找,但i没有定义,然后又到方法外部查找,此时有定义,但i的值是4(只有i大于4才会停止执行for循环),因此,就会取到该值——这正是闭包(匿名函数)要使用其外部作用域中变量的结果。而且,这也是由于匿名函数本身无法传递参数(故而无法维护自己的作用域)造成的。
2:解决办法
方法一:
window.onload = function(){
var oLis = document.getElementById("test").getElementsByTagName("li");
for(var i = 0;i < oLis.length;i ++){
(function(i){
oLis[i].onclick = function(){
alert(i); //0123
}
})(i);
}
}
解释:成功打印每个i的值,原理就是通过自执行函数,将变量i保存到这个自执行函数的参数中。
方法二:
window.onload = function(){
var oLis = document.getElementById("test").getElementsByTagName("li");
for(var i = 0;i < oLis.length;i ++){
oLis[i].index = i;
oLis[i].onclick = function(){
alert(this.index); //0123
}
}
}
解释:将每次循环得到的i,赋值给oLis[i]对象的index属性,在通过this指向,取出点击当前对象的index的值。
方法三:
window.onload = function(){
var oLis = document.getElementById("test").getElementsByTagName("li");
for(var i = 0;i < oLis.length;i ++){
oLis[i].onclick = (function(e){
return function(){
alert(e); //0123
}
})(i);
}
}
解释:
3:其他
window.onload = function(){
var oLis = document.getElementById("test").getElementsByTagName("li");
for(var i = 0;i < oLis.length;i ++){
oLis[i].onclick = a();
function a(){
alert(i); /0123
}
}
}
解释:虽然这样可以打印出每次变量i的值,但是我们没有点击li的时候他已经执行完了,也就是说,这个点击事件已经可有可无了,所以我们这种方法在绑定事件中不可用。
4:ES6为我们新增了,定义变量的关键字 let
window.onload = function(){
var oLis = document.getElementById("test").getElementsByTagName("li");
for(let i = 0;i < oLis.length;i ++){
oLis[i].onclick = function(){
alert(i); //0123
}
}
}
解释:let允许声明一个作用域被限制在块级中的变量、语句或者表达式。与var关键字不同的是,它声明的变量只能是全局或者整个函数块的。
let的几点用法:
1:用于声明变量,不做变量提升;
2:在同一个作用域中,不允许重复声明同一个变量;
3:会产生块级作用域{ };
4:特殊注意:for循环是一个块级作用域,for后{}是一个块级作用域,for块级作用域是for{}块级作用域的父级作用域。
for(let i = 0;i < 5;i++,console.log( i )){ 0 1 2 3 4
let i = 10;console.log( i ); 10 10 10 10 10
}
alert(i);//报错
循环执行了几次,就存几个块级作用域,每一个块级作用域都有一个变量 i ,但是这几个i不是同一个i 。(函数内部的变量i 与 循环变量i 不在同一个作用域,有各自单独的作用域)
for 循环中的 i 变量问题的更多相关文章
- 【Javascript】: for循环中定义的变量在for循环体外也有效
for循环中定义的变量在for循环体外也有效 <script> (function(){ var a = 111; for(var i=0;i<5;i++){ var carl = ...
- bash的循环中无法保存变量
在bash中,如果循环在一个子shell中运行,那么在循环中对循环外面的变量的更改将在循环退出后不可见.像下面的例子: #!/bin/sh python run.py | while read lin ...
- 11 tensorflow在tf.while_loop循环(非一般循环)中使用操纵变量该怎么做
代码(操纵全局变量) xiaojie=1 i=tf.constant(0,dtype=tf.int32) batch_len=tf.constant(10,dtype=tf.int32) loop_c ...
- (python)循环中动态产生变量
>>> for i in xrange(5): exec 'a'+str(i)+' = '+str(i)+'' >>> a0 0 >>> a1 1 ...
- js for 循环中的 变量问题。
今日处理项目中的一个循环,本来就是一个小小的for循环,后来发现该段程序出现了问题,仔细检查代码没有发现其中的错误.无奈只好叫来了老大帮忙.通过在模版中断点调试(该方式只能自己写debugger断点) ...
- 关于在for循环中绑定事件打印变量i是最后一次。
其实函数引用的外部变量都是最后一次的值. <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- 关于while read line 循环中变量作用域的问题
前一阵用shell写了一个从数据库中抽取数据生成.xml文件的脚本,要求是每个文件中只生成1000条数据.于是用到了while read line 作为循环. 在制作文件计数器的时候发现了一个问题,在 ...
- 【SQL】小心在循环中声明变量——浅析SQL变量作用域
本文适用:T-SQL(SQL Server) 先看这个语句: --跑3圈 BEGIN --每圈都定义一个表变量,并插入一行 DECLARE @t TABLE(Col INT PRIMARY KEY) ...
- 注意for循环中变量的作用域-乾颐堂
1 2 for e in collections: pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循 ...
随机推荐
- 【开发技术】Beyond Compare
黑色表示左右两侧的文件(夹)是一样的; 紫色表示右(左)侧是完全没有的,这时我们右击这个文件(夹),选择“复制到右(左)侧”即可: 红色表示两边都有这个文件(夹),但不完全相同,这时你就要权衡一下修改 ...
- MySQL主从复制的配置
环境 操作系统:CentOS-6.6-x86_64-bin-DVD1.iso MySQL版本:mysql-5.6.26.tar.gz 主节点IP:192.168.1.205 主机名:edu-m ...
- ZooKeeper集群的安装、配置、高可用测试
Dubbo注册中心集群Zookeeper-3.4.6 Dubbo建议使用Zookeeper作为服务的注册中心. Zookeeper集群中只要有过半的节点是正常的情况下,那么整个集群对外就是可用的.正是 ...
- RocketMQ环境搭建(双master双slave模式)
1.环境准备: 准备四台主机(我这里用CentOSx64) 主机 角色 broker 192.168.192.130 Master1 BrokerServerA 192.168.192.131 Mas ...
- 《Java编程的逻辑》终于上市了!
2018年1月下旬,<Java编程的逻辑>终于出版上市了! 这是老马过去两年死磕到底.无数心血的结晶啊! 感谢"博客园"的广大读者们,你们对老马文章的极高评价.溢美之词 ...
- Servlet--ServletContext接口
Servlet--ServletContext接口 定义public interface ServletContext 定义了一个 Servlet 的环境对象,通过这个对象,Servlet 引擎向 S ...
- 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
/** * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名. */ private function createSign($parameters,$key) { $signP ...
- 【转】Linux上vi(vim)编辑器使用教程
Linux上vi(vim)编辑器使用教程 ------------------------------------------------------------ ikong ------------ ...
- TCP粘包和拆包问题
问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况 ...
- ASP.NET Core Web APi获取原始请求内容
前言 我们讲过ASP.NET Core Web APi路由绑定,本节我们来讲讲如何获取客户端请求过来的内容. ASP.NET Core Web APi捕获Request.Body内容 [HttpPos ...