浅谈for循环中使用var出现的问题

for循环中使用var出现的问题

首先for循环是同步执行的,如果内部写的是同步代码是不会遇到索引值错误的。

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

一般来说问题出现考虑两点:

  1. var是函数作用域的。
  2. 事件循环中任务队列中的微任务和宏任务是当前事件循环的结束和下一次循环的开始执行的(当然最早的一次是宏任务,读取JavaScript代码)
for (var i = 0; i < 5; i++) {
      console.log(i);
      new Promise((resolve) => {
        resolve(i);
      }).then((result) => {
        console.log(`res=${result}`);
      });
      setTimeout(() => {
        console.log(i);
      }, 500);
    }

上面代码输出结果为 0~4, res=[0,4], 5个5,promise为微任务,setTimeout为宏任务。
这里就解释一下为什么setTimeout是5个5,但Promise输出的却是对的,这两个的行为其实类似,都是for循环结束后,才轮到他们执行,由于var的作用域不是块级的,for循环结束后var已经变成了5,因此setTimeout每次输出的值都是5,而Promise的值为什么是正确的如下代码,相信应该都看过。

    for (var i = 0; i < 5; ++i) {
      ((x) => {
        setTimeout(() => {
          console.log(x);
        }, 500);
      })(i);
    }

解释性的说法是:用立即执行函数并绑定当前传入这个闭包参数 i,因此即使是后面执行但每轮循环绑定的值已经不一样了。
最主要的应该是,这段代码的外层是同步代码,就和Promise的构造函数是同步代码一样,他们是立即执行的,因此Promise构造函数中的resolve的i是每次执行的而不是最后执行,then则是在setTimeout前执行。

let

再说一下let,事实上let所做到的就是将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。 一方面let也是块级作用域的。

var作为函数作用域常常污染外部变量,如下代码就是证明,最终输出结果是5个30。

    for (var i = 0; i < 5; ++i) {
        setTimeout(() => {
          console.log(i);
        }, 500);
    }
    i = 30;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值