前端复习1:从一道题分析JS事件循环机制

console.log('global')//第一个宏任务(整体script)进入主线程,打印a

for (var i = 1;i <= 5;i ++) {//注意这里定义了全局变量i
  setTimeout(function() {//遇到setTimeout,其回调函数进入宏任务队列
    console.log(i)
  },i*1000)
  console.log(i)//打印i
}

new Promise(function (resolve) {//遇到Promise,new Promise直接执行,打印promise1
  console.log('promise1')
  resolve()
 }).then(function () {//then进入微任务队列
  console.log('then1')
})

setTimeout(function () {//遇到setTimeout,其回调函数进入宏任务队列
  console.log('timeout2')
  new Promise(function (resolve) {
    console.log('timeout2_promise')
    resolve()
  }).then(function () {
    console.log('timeout2_then')
  })
}, 1000)

该段代码中要注意1:在第一次事件循环中,碰到for循环,for循环执行过程中,挂起了5个setTimeout函数,即它们的回调函数进入宏任务队列;当for循环走完,变量i已经称为固定值6,则之后setTimeout执行其回调函数的时候,打印的所有i应该都是6
打印结果
该段代码中要注意2:for循环中的i是用var 命令定义的,如果将var改为let,则结果不一样。
这是为什么?
查了一下廖雪峰老师ES6教程中let的用法:

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

我的理解是: let 是在for循环代码块内有效,因此用let 变量声名变量i 后,每次循环的i其实都是一个新的变量, 并且i 只在本轮循环中有效。而setTimeout定时器挂起的时候,其上下文环境是当前第i次for循环,所以就保存了i的值,即定时器保存的是不同的变量i
当for中使用let定义i

总结:
注意for循环体中使用let与var定义循环变量i的本质是不一样的。如果在
for循环体中引入setTimeout定时器,则用var定义的变量最后执行结果一致(因为var只声名一个变量,for循环结束后,变量不会再改变);而使用let定义的变量i,在每次for循环中都是新变量,所以与var的结果不一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值