/* 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; } } }