for循环读取i值

hello_pqq 2019-09-24 06:21:04
【主体】 (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     }   } } (2)原因解析 解析:因为在for循环里面指定给oLis[i].onclick的事件处理程序,也就是onclick那个匿名函数是在for循环执行完成后(用户点击时)才被调用的。而调用时,需要对变量i求值,解析程序首先会在事件处理程序内部查找,但i没有定义,然后又到方法外部查找,此时有定义,但i的值是4(只有i大于4才会停止执行for循环),因此,就会取到该值——这正是闭包(匿名函数)要使用其外部作用域中变量的结果。而且,这也是由于匿名函数本身无法传递参数(故而无法维护自己的作用域)造成的。 其实是根据作用域链的原理,在这个函数里面的i其实引用的是最后一次i的值,为什么不是0,1,2,3,...呢?因为在你for循环的时候,你并没有执行这个函数,你这个函数是在你点击的时候才执行的,当执行这个函数的时候,它发现它自己没有这个变量i,于是向它的作用域链中查找这个变量i,因为当你单击这个box的时候已经for循环完了,所以储存在作用域链里面的i的值就是4,最后就弹出出来4了。 (3)解决方案 ①匿名函数/自执行函数---将每次for循环中的变量i保存到某个地方 for(var i = 0;i < oLis.length;i ++){   (function(i){     oLis[i].onclick = function(){       alert(i); //0123     }   })(i); } 解释:成功打印每个 i 的值,原理就是通过自执行函数,将变量i保存到这个自执行函数的参数中。 ②自定义属性 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的值 ③闭包 for(var i=0;i<li_list.length;i++){ li_list[i].onclick = function(i){ return function(){ console.log(i) } }(i) } ④ES6为我们新增了,定义变量的关键字 let,实现块级作用域 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 不在同一个作用域,有各自单独的作用域)
...全文
178 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
jio可 2019-09-25
  • 打赏
  • 举报
回复
不支持es6用匿名函数,支持就用let
漠子凉 2019-09-24
  • 打赏
  • 举报
回复

	window.onload = function(){
		document.querySelector('#test').addEventListener('click', function(e) {
			if(e.target.nodeName == 'LI') {
				for( let i = 0; i < this.children.length; i++ ) {
					if( this.children[i] == e.target ) {
						console.log(i); // 索引
					}
				}
			}
		})
	}

87,909

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧