Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
一、第一题
- 题目内容:得出下面一段代码的输出
- 输出为:5555
- 这里考察的是等待队列和作用域,setTimeout属于异步任务,当执行每一循环时,并不会立即执行setTimeout函数,而是将执行setTimeout函数这个任务放到等待队列中,等到主线程空闲了再依次执行等待队列中的任务,而这里要等到for循环执行完毕主线程才会空闲,此时i = 5,又因为var声明的变量是全局变量,所以每一轮循环的i值没有保存到对应任务的作用域中,所以当执行等待队列中的任务时,查询到的i都是全局变量i,即都会输出5
二、输出501234
- 题目内容:保持第一题的for循环,循环范围不变,输出501234
1、自执行函数实现
- 这里利用了闭包的特点:父函数的所有变量对子函数可见;子函数未执行完毕,父函数作用域内的变量不会被垃圾回收机制回收。当执行for循环时,每一轮循环都会将setTimeout异步任务放到等待队列中,而且都会为setTimeout函数创建一个作用域,在这个作用域里会保存setTimeout函数的父函数的变量j(传进来的i),由于每一轮都是新的作用域,相互不影响,所以每个作用域的i值都不同。当for循环执行完毕i=5,就执行最后一行代码
console.log(i);,打印i=5。此时主线程处于空闲状态,就会依次执行等待队列中的任务,即依次输出01234
2、函数方式实现
- 这个方法和自执行方法原理类似,它利用函数在每次执行for循环时创建的作用域保存不同i值
3、ES6的let实现
- 这个方法利用的就是let声明的变量有块级作用域
三、输出012345
- 题目内容:保持第一题的for循环,循环范围不变,输出501234
1、自执行函数实现
- 这个方法也是利用闭包让i值不同,同时利用设置setTimeout的等待时间,让5最后打印
2、promise实现
- 利用闭包闭包保存不同的i值
- 这个方法就是利用promise定义多个异步任务,然后按照执行顺序将他们放到一个任务队列中,
Promise.all()方法会并发执行任务队列(tasks数组)中的异步任务,当这些任务执行全部完毕后,再打印5。所以任务队列中的打印需要使用setTimeout来控制打印的顺序,等待时间越短越先执行,而最后打印5的代码出就可以不需要setTimeout,因为它会等待tasks中的任务全部执行完毕才会执行
3、函数方式实现
- 这个方法同上一个方法类似,不同的是利用函数执行时创建的作用域保存了不同的i值