Создание собственного итератора для класса | Creating a custom iterator for the class

Для того чтобы перебирать объект методом for...of, в него нужно добавить итератор. Создадим простой класс итератор.

class TaskList {
    constructor() {
        this.tasks = [];
    }
    addTasks(...tasks) {// используем оператор разворота чтобы множество элементов превратить в массив
        this.tasks = this.tasks.concat(tasks);
    }
    [Symbol.iterator]() {
		let tasks = this.tasks;
		let index = 0;
        return {
			next() {
				let result = { value: undefined, done: true };
				if (index < tasks.length) {
					result.value = tasks[index];
					result.done = false;
					index += 1;
				}
				return result;
			}
		};
    }
}

let taskList = new TaskList();
taskList.addTasks('Изучить JavaScript', 'Изучить ES6', 'Купить продукты');

for (let task of taskList) {
    console.log(task);
}
// Изучить JavaScript
// Изучить ES6
// Купить продукты

Код работает но он не очень хорошо. Кадый раз для создания нового итератора в классе придётся дублировать код итератора. Правильнее выделить код итератора в отдельный класс.

class ArrayIterator {
    constructor(array) {
        this.array = array;
		// вариант сортировки в алфавитном порядке
		// this.array = array.map(item => item).sort();
        this.index = 0;
    }
    next() {
        let result = { value: undefined, done: true };
                
        if (this.index < this.array.length) {
            result.value = this.array[this.index];
            result.done = false;
            this.index += 1;
        }
        return result;
    }
}

class TaskList {
    constructor() {
        this.tasks = [];
    }
    addTasks(...tasks) {
        this.tasks = this.tasks.concat(tasks);
    }
    [Symbol.iterator]() {
        return new ArrayIterator(this.tasks);
    }
}

let taskList = new TaskList();
taskList.addTasks('Изучить JavaScript', 'Изучить ES6', 'Купить продукты');

for (let task of taskList) {
    console.log(task);
}