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 变量问题的更多相关文章

  1. 【Javascript】: for循环中定义的变量在for循环体外也有效

    for循环中定义的变量在for循环体外也有效 <script> (function(){ var a = 111; for(var i=0;i<5;i++){ var carl = ...

  2. bash的循环中无法保存变量

    在bash中,如果循环在一个子shell中运行,那么在循环中对循环外面的变量的更改将在循环退出后不可见.像下面的例子: #!/bin/sh python run.py | while read lin ...

  3. 11 tensorflow在tf.while_loop循环(非一般循环)中使用操纵变量该怎么做

    代码(操纵全局变量) xiaojie=1 i=tf.constant(0,dtype=tf.int32) batch_len=tf.constant(10,dtype=tf.int32) loop_c ...

  4. (python)循环中动态产生变量

    >>> for i in xrange(5): exec 'a'+str(i)+' = '+str(i)+'' >>> a0 0 >>> a1 1 ...

  5. js for 循环中的 变量问题。

    今日处理项目中的一个循环,本来就是一个小小的for循环,后来发现该段程序出现了问题,仔细检查代码没有发现其中的错误.无奈只好叫来了老大帮忙.通过在模版中断点调试(该方式只能自己写debugger断点) ...

  6. 关于在for循环中绑定事件打印变量i是最后一次。

    其实函数引用的外部变量都是最后一次的值. <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  7. 关于while read line 循环中变量作用域的问题

    前一阵用shell写了一个从数据库中抽取数据生成.xml文件的脚本,要求是每个文件中只生成1000条数据.于是用到了while read line 作为循环. 在制作文件计数器的时候发现了一个问题,在 ...

  8. 【SQL】小心在循环中声明变量——浅析SQL变量作用域

    本文适用:T-SQL(SQL Server) 先看这个语句: --跑3圈 BEGIN --每圈都定义一个表变量,并插入一行 DECLARE @t TABLE(Col INT PRIMARY KEY) ...

  9. 注意for循环中变量的作用域-乾颐堂

    1 2 for e in collections:     pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循 ...

随机推荐

  1. OpenCV3.4两种立体匹配算法效果对比

    以OpenCV自带的Aloe图像对为例:     1.BM算法(Block Matching) 参数设置如下: ) + ) & -; cv::Ptr<cv::StereoBM> b ...

  2. cobol

    过程部的语句一般从B区开始书写. ACCEPT A,B (x)       DISPLAY T1,T2.(O)显示在一行上 DISPLAY  T1 DISPLAY  T2 (O)显示在两行上 read ...

  3. [机器学习]-[数据预处理]-中心化 缩放 KNN(二)

    上次我们使用精度评估得到的成绩是 61%,成绩并不理想,再使 recall 和 f1 看下成绩如何? 首先我们先了解一下 召回率和 f1. 真实结果 预测结果 预测结果   正例 反例 正例 TP 真 ...

  4. label+input实现开关切换效果

    Document 主要使用label+input来实现改变left的值,下面是核心代码,意思就是选中的input的兄弟节点.box下的.switch-btn元素的left会变成0px(原来是-37px ...

  5. mysql 安装以及配置

    MySQL是一个小巧玲珑但功能强大的数据库,目前十分流行.但是官网给出的安装包有两种格式,一个是msi格式,一个是zip格式的.很多人下了zip格式的解压发现没有setup.exe,面对一堆文件一头雾 ...

  6. __new__、__init__、__call__三个特殊方法

    用双下划线包围的特殊方法在Python中又被成为魔术方法,类似于C++等语言中的构造函数,这里我们就来详解Python中的__new__.__init__.__call__三个特殊方法: 1.__ne ...

  7. 主页面刷新 illegalStateException:stream

    其实是:jsonmappingexception:no serializer found for class 由于后台错误堆栈打印很快,只看到illegalStateException:stream ...

  8. Linux指令--mkdir

    本篇博客参照http://www.cnblogs.com/peida/archive/2012/10/25/2738271.html. linux mkdir 命令用来创建指定的名称的目录,要求创建目 ...

  9. android onSaveInstanceState应用实例

    //activity销毁之前调用,把状态值存储上 @Override protected void onSaveInstanceState(Bundle outState) { outState.pu ...

  10. Android5.0新控件

    谷歌在推出Android5.0的同时推出了一些新控件,Android5.0中最常用的新控件有下面5种.  1. CardView(卡片视图) CardView顾名思义是卡片视图,它继承FrameLay ...