for循环作用域问题(var和let)

看这个:

var arr = []
for(var i = 0; i < 10; i++){
    arr[i] = function () {
        console.log(i)
    }
}
arr[0](); // 10
arr[1](); // 10
arr[2](); // 10
arr[3](); // 10

还有这个:

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
<script>
    // 获取元素
    var lis = document.querySelectorAll('li');
    for(var i = 0; i<lis.length; i ++){
        lis[i].onclick = function(){
        	console.log(i);//5  不能使用i
        }
    }
</script>

这里是这个全局变量i出了问题,以上js相当于:

{
	var i=0;
    lis[0].onclick = function(){
   		console.log(i);
   }
}
{
	var i=1;
    lis[1].onclick = function(){
   		console.log(i);
   }
}
{
	var i=2;
    lis[2].onclick = function(){
   		console.log(i);
   }
}

……
{
	var i=4;
    lis[4].onclick = function(){
   		console.log(i);
   }
}
{
	var i = 5;
}

当点击事件触发时,for循环已经执行结束了,由于i是var定义的,后面定义的i会覆盖前面的,所以最后i为5,当执行函数时,函数内没有i,根据作用域链向父级找,得到的是全局变量i = 5。
同样,把var换成let:

{
	let i=0;
    lis[0].onclick = function(){
   		console.log(i);
   }
}
{
	let i=1;
    lis[1].onclick = function(){
   		console.log(i);
   }
}
{
	let i=2;
    lis[2].onclick = function(){
   		console.log(i);
   }
}

……
{
	let i=4;
    lis[4].onclick = function(){
   		console.log(i);
   }
}
{
	let i = 5;
}

let定义的i作用域仅在他所在的花括号内,几个花括号的i互不影响,函数向上级找到的i自然都不同。
把var换成let就能解决,或者:

for(var i = 0; i<lis.length; i ++){
    lis[i].index = i;
    lis[i].onclick = function(){
    //console.log(i);//5  不能使用i
    // 输出每一个li的下标
    console.log(this.index);//0 1 2 3 4
    }
}

同样,以下代码为例,应该也可以理解了:

var arr = []
for(var i = 0; i < 3; i++){
    arr[i] = function () {
        console.log(i)
    }
}
arr[0](); // 3
arr[1](); // 3
arr[2](); // 3

for循环的执行过程为:

{
	var i=0;
	arr[0] = function () {
		console.log(i)
	}
}
{
	var i=1;
	arr[1] = function () {
		console.log(i)
	}
}
{
	var i=2;
	arr[2] = function () {
		console.log(i)
	}
}
{
	var i=3;
}

再看这个:

for(var i = 0; i < 5;i ++){
	console.log(i);//0 1 2 3 4
   	setTimeout(function(){
       	console.log(i)//5 5 5 5 5
   	},0)
}

如上:输出结果为 5 5 5 5 5,按照前面的思路似乎可以理解了

有点晕,又好像没晕

for(var i = 0; i < 5;i ++){
    function f1(){
        console.log(i)
    }
}
f1();//5

我们知道输出是5,但如果把函数的执行在里面

for(var i = 0; i < 5;i ++){
    f1();//0 1 2 3 4
    function f1(){
        console.log(i)
    }
}

就是0 1 2 3 4
额、、是因为立即执行的原因吗
前面的setTimeout(function(){},0)不是立即执行吗?两者如何判断?

尝试验证:

for(var i = 0,a = 1; i < 5;i ++){//1 2 3 4 5
    console.log(a);//1 1 1 1 1
    setTimeout(function(){
        a++;
        console.log(i)//5 5 5 5 5
    },0)
}

输出结果为:先输出5个1,后输出5个5
由此可见,整个for循环执行完才开始执行setTimeout函数,所以它不是立即执行。。。

可以配合this指向问题食用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值