栈,堆,队列的特点
- 栈: 有结构,有序,先进后出
- 队列: 有结构,有序,先进先出
- 堆: 无结构,无序
栈,堆的定义与对比
- 栈:可以存放有结构,有顺序的数据,可用于存放js的基本数据类型(Number/String/Boolean/null/undefined)和对象的引用,存放的数据大小和生命周期是确定的
- 堆:存放的数据无结构,无顺序,可用于存在js的引用类型(数组对象,object对象)
- 栈的寻址速度大于堆,这是由于栈中保存基本数据类型的key和value,而只保存堆中value所对应的key

解读浏览器的任务队列
- 当浏览器执行js代码时,若遇到setTimout定时器,DOM操作,ajax等会交给浏览器的webAPIs,webAPIs会把这些异步任务根据类型放置在同源的宏任务队列中
- 当遇到promise的then回调,nextTick,await后的事件等会放被浏览器放置到同源的微任务队列中
- js只有一个主线程,主线程只能执行一个任务栈,当执行完任务栈中的任务后,会从任务队列中获取任务并执行(若任务队列中存在微任务,则按照顺序首先执行微任务,后执行宏任务),而任务队列会从webAPIs中不断获取任务,此过程称为事件循环
题目一

解读:js自上而下执行,首先输出1,遇到定时器,丢给webAPIs(放入宏任务队列),往下遇到promise执行输出3,里面的定时器继续丢给webAPIS(放入第二个宏任务队列),promise1的then回调放到微任务队列中,输出5;此时栈中任务全部完成,然后再执行微任务队列,输出4,后执行宏任务队列的定时器事件,输出2,当宏任务队列执行完成后会执行下一个微任务队列,若没有,则执行下个宏任务队列,依次类推
题目二

解读:当循环中遇到定时器,丢给WebAPIs同时传递此时的i值,并依次放入宏任务队列中,执行栈先打印for循环中的输出后,再读取宏任务队列并执行
题目三

解读:此题目主要考察微任务队列,需注意一点的是await后的事件会产生微任务,并非等待await执行完后立刻执行函数内剩余的事件

- 宏任务队列:定时器,ajax,dom操作...
- 微任务队列:nextTick,Promise.then(),await后的事件
设计一个循环队列
通常的任务队列,若队列已满,即便队列中任务执行完有空余,也不能插入新的任务,循环队列可以复用同一个队列,达到节约性能的作用
要求
- MyCircularQueue(k): 构造器,设置队列⻓度为 k 。
- Front: 从队⾸获取元素。如果队列为空,返回 -1 。
- Rear: 获取队尾元素。如果队列为空,返回 -1 。
- enQueue(value): 向循环队列插⼊⼀个元素。如果成功插⼊则返回真。
- deQueue(): 从循环队列中删除⼀个元素。如果成功删除则返回真。
- isEmpty(): 检查循环队列是否为空。
- isFull(): 检查循环队列是否已满。
实现
class MyCircularQueue1 {
// 构造函数,唯一
constructor (k) {
this.capacity = k // 保存循环队列的长度
this.head = 0 // 队列开头,队列移除任务则加一
this.tail = 0 // 队列结尾,队列新增任务则加一
this.data = [] // 队列数据
}
// 判断队列是否为空
isEmpty () {
return this.head === this.tail
}
// 判断队列是否已满
isFull () {
if (this.tail - this.head === this.capacity) {
return true
}
return false
}
// 从队首获取元素,如果队列为空,则返回-1
Front () {
if (!this.isEmpty()) {
return this.data[this.head % this.capacity]
}
return -1
}
// 从队尾获取元素,如果队列为空,则返回-1
Rear () {
if (!this.isEmpty()) {
return this.data[(this.tail-1) % this.capacity]
}
return -1
}
// 向循环队列中插入一个元素,成功插入返回true
enQueue (value) {
if (!this.isFull()) {
this.data[this.tail % this.capacity] = value
this.tail++
return true
}
return false
}
// 向循环队列中删除一个元素,成功删除返回true
deQueue () {
if (!this.isEmpty()) {
this.head++
return true
}
return false
}
}