前言

yocto-queue作用

什么是链表?

什么是迭代器&生成器?

生成器

在 JavaScript 中,迭代器是一个对象,它定义一个序列,并在终止时可能返回一个返回值。 更具体地说,迭代器是通过使用next() 方法实现 Iterator protocol 的任何一个对象,该方法返回具有两个属性的对象: value,这是序列中的 next 值;和 done ,如果已经迭代到序列中的最后一个值,则它为 true 。如果 value 和 done 一起存在,则它是迭代器的返回值。

链表与数组的区别

源码

yocto-queue框架

  1. class Node {}
  2. export default class Queue {
  3. #head; // 指向头指针
  4. #tail; // 指向当前节点
  5. #size; // 当前队列元素个数
  6. // 构造函数
  7. constructor () {}
  8. // 向队列中添加一个值
  9. enqueue (value) {}
  10. // 删除队列中的下一个值
  11. dequeue () {}
  12. // 清空队列
  13. clear () {}
  14. // 清空队列
  15. get size () {}
  16. *[Symbol.iterator] () {}
  17. }

node类

  1. class Node {
  2. value; // 当前节点值
  3. next; // 指向后一个节点
  4. constructor(value) {
  5. this.value = value;
  6. }
  7. }

这里使用到了设计模式中的工厂模式,使用node类实例化出来的对象,都有valuenext这两个字段

constructor 构造方法

  1. constructor() {
  2. this.clear();
  3. }

构造函数只是调用了一下清空队列的方法

这里的clear()方法主要起设置初始值的作用,比如上面虽然定义了size字段,但是并未赋值

clear()方法中有一段this.#size = 0正好可以给size赋初始值,提高代码复用

enqueue

  1. enqueue (value) {
  2. const node = new Node(value);
  3. if (this.#head) {
  4. this.#tail.next = node;
  5. this.#tail = node;
  6. } else {
  7. this.#head = node;
  8. this.#tail = node;
  9. }
  10. this.#size++;
  11. }

dequeue

  1. dequeue () {
  2. const current = this.#head;
  3. if (!current) {
  4. return;
  5. }
  6. this.#head = this.#head.next;
  7. this.#size--;
  8. return current.value;
  9. }

clear

  1. clear () {
  2. this.#head = undefined;
  3. this.#tail = undefined;
  4. this.#size = 0;
  5. }

size

  1. get size () {
  2. return this.#size;
  3. }

Symbol.iterator

  1. *[Symbol.iterator] () {
  2. let current = this.#head;
  3. while (current) {
  4. yield current.value;
  5. current = current.next;
  6. }
  7. }

代码作用

这里是为了让实例化出来的对象可以被 for...of 循环
默认情况下,实例化出来的对象是不能循环的,比如这里我们注释掉Symbol.iterator代码部分,打印时浏览器就会提示错误

  1. export default class Queue {
  2. // 其余代码...
  3. // *[Symbol.iterator] () {
  4. // 内部代码...
  5. // }
  6. }
  7. const queue = new Queue();
  8. queue.enqueue('🦄');
  9. queue.enqueue('🌈');
  10. queue.enqueue('🦄');
  11. for (let i of queue) {
  12. console.log(i)
  13. }
  14. // TypeError: queue is not iterableat <anonymous>:78:15

然后我们再取消Symbol.iterator注释,再打印试一下

  1. export default class Queue {
  2. // 其余代码...
  3. // 取消注释 Symbol.iterator
  4. *[Symbol.iterator] () {
  5. // 内部代码...
  6. }
  7. }
  8. const queue = new Queue();
  9. queue.enqueue('🦄');
  10. queue.enqueue('🌈');
  11. queue.enqueue('🦄');
  12. for (let i of queue) {
  13. console.log(i)
  14. }
  15. // 可以正常打印
  16. // 🦄🌈🦄

代码解析

首先函数声明部分是使用了一个简写,这段代码等同于

  1. [Symbol.iterator] = function* () {
  2. let current = this.#head;
  3. while (current) {
  4. yield current.value;
  5. current = current.next;
  6. }
  7. }

第一部分 什么是 Symbol.iterator function* () ?

总结

参考