关于 for 循环中 i 的值

不知道大家有没有发现一个问题,当在一个 for 循环中直接打印 i 时候,i 的值并不是我们想的那样。
html代码

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

先获取到页面中的li

 var lis=document.querySelectorAll('ul li');

然后来个 for 循环

for(var i=0;i<lis.length;i++){
  lis[i].addEventListener('click',function(){
      console.log(i);//都是3
  },false);
}

我们会发现,当点击 li 时,输出的 i 的值不是我们想的0 1 2, 而是3,可能我们会认为i<lis.length=3,咋也不可能等于3鸭!
这里涉及到同步&异步的概念。
事件的执行是异步的,异步代码会被置于一个特殊的等待队列中,它只会在浏览器“有空闲时间”的时候才会执行
说人话就是console.log(i)被浏览器放在一边等待,(因为只绑定click事件,而不运行其中代码)等浏览器“有空”的时候,就是循环绑定完事件后,这时 i 已经自增到3了,所以打印出来都是3。(i=2时人家还在循环,等于3才跳出循环)

那么如何解决这个问题呢
法一:将var改成let

for(let i=0;i<lis.length;i++){
   lis[i].addEventListener('click',function(){
       console.log(i);//0 1 2
   },false);
}

这样就解决了,那么为什么呢?
我们先来说说let,ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
也就是说var声明的是全局变量,而let声明的是局部变量
var声明只声明了一个共享的全局变量 i ,而let声明多个 i ,i = 0,i = 1…
每个 i 只对当前的区域有效。

法二:封装成一个匿名立即执行函数 并定义一个局部变量j

for(var i=0;i<lis.length;i++){
   (function(j){
       lis[i].addEventListener('click',function(){
           console.log(j);
       },false);
   })(i);//将i作为参数传给j
}

这里的关键也是局部变量,封装成函数相当于另外开辟出一块区域,然后在里边定义一个局部变量j。

法三:保存当前对象的索引

for(let i=0;i<lis.length;i++){
    lis[i].index=i;
    lis[i].addEventListener('click',function(){
        console.log(this.index);//0 1 2
    },false);
}

如果前面两个不是很好理解的话可以看下法三,和法二相似,将 i 赋值给lis[ i ].index,保存当前对象的索引,然后输出this.index

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值