- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第32期,链接:[【若川视野 x 源码共读】第32期 |【若川视野 x 源码共读】第32期 | yocto-queue 队列 链表 - 掘金 (juejin.cn)
本来应该上周末完成这篇文章,家里有事给耽误了,所以本周准备完成两篇,追上本来计划好的进度
跑代码时,一直提示证书过期 "https://registry.npm.taobao.org/ava: certificate has expired".试着搜了一些解决办法,然而并没有解决这个问题,那就先放一放,直接看源码,
/*
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.
*/
// 上面的英文部分其实也能看明白
//queue中存储的每一个值都是Node实例
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;
}
}
}
源码部分重点在于[Symbol.iterator],要想搞懂这里,还得学习下面的概念
- 生成器函数
function*和关键字yield - 以及由
function*返回的Generator对象 - 最后是配合
Symbol.iterator属性的使用
生成器函数和yield的基本用法
MDN的解释很清晰function* - JavaScript | MDN (mozilla.org)
我在浏览器上尝试了一番
注意Generator对象中的有个属性[[GeneratorState]]在没有迭代完事是suspended迭代完成时事closed也就是说生成器函数构造了一个可按某种逻辑迭代的generator对象,这个对象有个方法next(),每次都返回一个{value: ,done: }形式的对象,当其中done为true时,迭代结束
迭代协议
感觉有点越挖越深 迭代协议 - JavaScript | MDN (mozilla.org)
总结
[Symbol.iterator]的使用function*与yield的使用