yocto-queue 队列
本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
yocto-queue
该库使用js实现了一个简单队列
- size获取当前队列的长度
- dequeue() 删除头部,返回被删除的项
- enqueue() 从队列尾部添加一项
- 可以使用扩展运算符,将队列通过数组返回
解析
源代码
/*
How it works:
`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
*/
class Node {
value;
next;
constructor(value) {
this.value = value;
}
}
export default class Queue {
#head;
#tail;
#size;
constructor() {
this.clear();
}
enqueue(value) {
const node = new Node(value);
if (this.#head) {
this.#tail.next = node;
this.#tail = node;
} else {
this.#head = node;
this.#tail = node;
}
this.#size++;
}
dequeue() {
const current = this.#head;
if (!current) {
return;
}
this.#head = this.#head.next;
this.#size--;
return current.value;
}
clear() {
this.#head = undefined;
this.#tail = undefined;
this.#size = 0;
}
get size() {
return this.#size;
}
* [Symbol.iterator]() {
let current = this.#head;
while (current) {
yield current.value;
current = current.next;
}
}
}
初始化
这里使用了es6新增的class语法,在每次创建该构造对象时,使用了clear方法,清空了#head,#tail,#size
为了防止外部修改状态,使用了私有属性,其中#为es6新增的语法糖
这里有个Node构造函数,存储next下一个指向和value当前值,用于队列中添加的数据项
新增
调用enqueue,先判断当前#head是否存在值。
- 如果不存在,代表第一次添加,将创建的node添加给#head 和 #tail。
- 如果存在,
#tail此时为队列尾部,将node 赋值给#tail.next,并且将node赋值给#tail,这样上一次的尾部指向这次的node 实现了尾部链接
删除
调用dequeue,优先判断#head是否存在
- 如果不存在代表没有值可以删除,返回空。
- 如果存在,将当前#head的next赋值给#head,返回之前的#head.value
获取长度
这里使用了一个访问器,返回了私有变量#size
扩展运算符返回数组
由于扩展运算符(...)也会调用默认的 Iterator 接口 这里实现了Symbol.iterator方法, 这里通过一个while循环,判断当前#head的value值,如果#head存在就yield 当前的value值,从而实现个Iterator
测试
该库使用ava进行测试 对其几个方法进行测试,
- is断言来判断
t.is(queue.dequeue(), '🌈'); - deepEqual断言来测试interator接口
t.deepEqual([...queue], [1,2,3]);
结束语
通过阅读yocto-queue,学习了队列的实现,ava测试的使用,扩展运算符的实现需要遍历器Iterator,es6新增的class语法的使用