前言
yocto-queue作用
什么是链表?
什么是迭代器&生成器?
生成器
在 JavaScript 中,迭代器是一个对象,它定义一个序列,并在终止时可能返回一个返回值。 更具体地说,迭代器是通过使用
next()
方法实现 Iterator protocol 的任何一个对象,该方法返回具有两个属性的对象: value,这是序列中的 next 值;和 done ,如果已经迭代到序列中的最后一个值,则它为 true 。如果 value 和 done 一起存在,则它是迭代器的返回值。
链表与数组的区别
源码
yocto-queue框架
class Node {}
export default class Queue {
#head; // 指向头指针
#tail; // 指向当前节点
#size; // 当前队列元素个数
// 构造函数
constructor () {}
// 向队列中添加一个值
enqueue (value) {}
// 删除队列中的下一个值
dequeue () {}
// 清空队列
clear () {}
// 清空队列
get size () {}
*[Symbol.iterator] () {}
}
node类
class Node {
value; // 当前节点值
next; // 指向后一个节点
constructor(value) {
this.value = value;
}
}
这里使用到了设计模式中的工厂模式,使用node类实例化出来的对象,都有value
和next
这两个字段
constructor 构造方法
constructor() {
this.clear();
}
构造函数只是调用了一下清空队列的方法
这里的clear()
方法主要起设置初始值的作用,比如上面虽然定义了size
字段,但是并未赋值
clear()
方法中有一段this.#size = 0
正好可以给size
赋初始值,提高代码复用
enqueue
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
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;
}
size
get size () {
return this.#size;
}
Symbol.iterator
*[Symbol.iterator] () {
let current = this.#head;
while (current) {
yield current.value;
current = current.next;
}
}
代码作用
这里是为了让实例化出来的对象可以被 for...of
循环
默认情况下,实例化出来的对象是不能循环的,比如这里我们注释掉Symbol.iterator
代码部分,打印时浏览器就会提示错误:
export default class Queue {
// 其余代码...
// *[Symbol.iterator] () {
// 内部代码...
// }
}
const queue = new Queue();
queue.enqueue('🦄');
queue.enqueue('🌈');
queue.enqueue('🦄');
for (let i of queue) {
console.log(i)
}
// TypeError: queue is not iterableat <anonymous>:78:15
然后我们再取消Symbol.iterator
注释,再打印试一下
export default class Queue {
// 其余代码...
// 取消注释 Symbol.iterator
*[Symbol.iterator] () {
// 内部代码...
}
}
const queue = new Queue();
queue.enqueue('🦄');
queue.enqueue('🌈');
queue.enqueue('🦄');
for (let i of queue) {
console.log(i)
}
// 可以正常打印
// 🦄🌈🦄
代码解析
首先函数声明部分是使用了一个简写,这段代码等同于
[Symbol.iterator] = function* () {
let current = this.#head;
while (current) {
yield current.value;
current = current.next;
}
}