理解for循环中的异步取值问题—五道题就够了

理解for循环中的异步取值问题—五道题就够了

复习:js单线程、事件循环、任务队列、执行顺序、异步、作用域、闭包

JS深入理解闭包/作用域(scope)、作用域链/执行上下文和执行栈
彻底搞懂js事件循环机制/js异步编程

一、var声明变量
(1)栗子1
for (var t1=0;t1<4;t1++){
   setTimeout(function(){console.log(t1)}, 1000)
}
//4 4 4 4 

在这里插入图片描述

解析:js是单线程的,js分为同步任务和异步任务,同步任务在主线程上进行,异步任务在异步队列里面不进入主线程。定时器排队在异步任务队列的队尾。当定时器时间到了且主线程空闲的时候会去异步任务队列调用任务进入主线程。

为什么输入是4,4,4,4,不是0,1,2,3呢?

for循环圆括号()里面的代码是同步代码,同步代码执行完毕后,for循环里面 i 的值已经变成4,循环已经结束。因为setTimeout的 i 值是全局变量,for形成一个块级作用域,全局变量可以跨块级作用域,每次循环这个值都会被改变,指向的是最外层全局变量 i 的值。1s打印的时候,i 已经变成4了。

(2)栗子2

有人说,用立即执行函数就可以避免回调。如果匿名立即执行函数呢?结果是怎么样的,我们用匿名立即执行函数试试看。

立即执行函数就是字面意思,代码加载后立即执行,无需等待回调。

//匿名立即执行函数不传入形参
for (var t1=0;t1<4;t1++){
   (function(){
      setTimeout(()=>{console.log(t1)}, 1000)
   })(t1)
}
// 4 4 4 4

在这里插入图片描述

解析:为什么输出还是4,4,4,4,不是0,1,2,3呢?明明用了立即执行函数了!这就涉及到闭包。

匿名立即执行函数没有传入形参,传入实参t1。在立即执行函数创建的作用域里面没有找到t1,会往外查找,就找到了t1,(闭包)这时候t1是var声明的全局变量,for同步代码执行后t1的值早已经为4。四个定时器里面的匿名函数共享了同一作用域里面的同一个变量,所以打印4,4 ,4 ,4。

(3)栗子3
//匿名立即执行函数传入形参
for (var t1=0;t1<4;t1++){
   (function(t1){
      setTimeout(()=>{console.log(t1)}, 1000)
   })(t1)
}
// 0 1 2 3

在这里插入图片描述

解析:为什么传入形参之后就可以打印出0,1,2,3了呢?

匿名立即执行函数传入形参,每个t1的值都会传入function声明的匿名立即执行函数,利用闭包使得函数可以继续访问定义时的作用域,每次循环的时候,新生成的作用域将每一次循环的 t1 值保存下来,所以打印出0,1,2,3。

二、let声明变量

let是ES6新增的声明变量,let可以声明一个独立的块级作用域。

(1)栗子1
for (let t1=0;t1<4;t1++){
   setTimeout(function(){console.log(t1)}, 1000)
}
// 0 1 2 3

在这里插入图片描述

解析:var换成let声明之后,为什么输出0,1,2,3?

let声明一个独立的块级作用域,在每个块级作用域里面的 t1 都是属于该作用域的,即每个作用域都有它自己的 t1。在for循环中用let来定义循环变量,每一次循环都会重新声明变量t1,随后的每个循环都会使用上一个循环结束时的值来初始化这个变量t1。

(2)栗子2
for (let t1=0;t1<4;t1++){
   (function(e) {
     setTimeout(function(){console.log(e)}, 1000)
   })(t1);
}
// 0 1 2 3 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傲娇味的草莓

佛系少女只是想记录学习痕迹

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值