本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
yocto-queue 处理什么问题?
引用该yocto-queue的一句话:
You should use this package instead of an array if you do a lot of
Array#push()
andArray#shift()
on large arrays, sinceArray#shift()
has linear time complexity O(n) whileQueue#dequeue()
has constant time complexity O(1). That makes a huge difference for large arrays. 针对 先进先出 这种场景,数组Array#shift()
所需的时间复杂度较高O(n)
(需要将后面的元素向前移动)。yocto-queue 内部通过链表的实现方式,将复杂度降到O(1)
,从而优化该场景下的性能。
阅读该源码可以学到什么?
- 队列实现方式
- Symbol.iterator使用
- 了解单元测试库ava
内部怎么实现的?
Node节点实现
class Node {
value;// 存储当前值
next;// 存储下一个节点指针
constructor(value) {
this.value = value;
}
}
整体API
export default class Queue {
#head;// 指向头指针
#tail;// 指向当前节点
#size;// 当前队列元素个数
constructor() {
this.clear();
}
// 入队
enqueue(val) {}
// 出队
dequeue() {}
// 清空
clear() {}
// 当前队列元素个数
get(){}
队列API实现
enqueue
enqueue(value) {
const node = new Node(value);
if (this.#head) {
// tail.next 指向下一个节点,tail指向当前节点(当前value所在的节点)
this.#tail.next = node;
this.#tail = node;
} else {
// 首次入队,head 和 tail 都指向第一个节点
this.#head = node;
this.#tail = node;
}
// 队列元素个数 + 1
this.#size++;
}
dequeue
dequeue() {
// 获取头结点
const current = this.#head;
// 空队列,直接返回
if (!current) {
return;
}
// 头结点指向下一个节点
this.#head = this.#head.next;
// 队列元素个数减一
this.#size--;
return current.value;
}
clear
clear() {
// 直接置空操作
this.#head = undefined;
this.#tail = undefined;
this.#size = 0;
}
Symbol.iterator使用
Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被
for...of
循环使用。 我们看看yocto-queue内部是怎么实现的:
* [Symbol.iterator]() {
let current = this.#head;
// 通过循环,不断挪动指针获取到值
while (current) {
yield current.value;
current = current.next;
}
}
通过上述实现,我们可以通过for...of
获取到队列中的值
const queue = new Queue();
queue.enqueue('🦄');
queue.enqueue('🌈');
console.log([...queue]); // 输出:['🦄', '🌈']
ava 单元测试
- 官网:github.com/avajs/ava
- 简介:一个轻量高效、高并发、简单测试语法的测试运行库。
- demo:
import test from 'ava'; test('foo', t => { // 测试通过 t.pass(); }); test('bar', async t => { const bar = Promise.resolve('bar'); // 判断两个值是否相等 t.is(await bar, 'bar'); });
从yocto-queue源码中可以看出,主要针对暴露的API进行功能测试,也为开发者了解其API的使用。
总结
从yocto-queue源码中,可以学习队列实现方式以及对应API的单元测试的完整过程;了解到链表与数组的一些区别以及Symbol.iterator
的使用场景。