Этот материал меня постоянно смущает, поэтому вот краткое изложение, к которому мы оба можем обратиться.
Вот фон
iterable
- это объект, имеющий * Свойство 1008 *, а затем вы, когда вы вызываете это свойство как функцию, возвращает объект итератора.
Объект итератора имеет свойство .next()
, и каждый раз, когда вы вызываете эту функцию, он возвращает объект с ожидаемые свойства {value: x, done: false}
. Объект итератора обычно сохраняет состояние итерации в этом отдельном объекте (таким образом, итераторы могут быть независимы друг от друга).
Таким образом, чтобы поддерживать несколько итераторов, вы создаете несколько методов, где каждый метод возвращает объект, который является разные итерируемые, каждый имеет свой собственный [Symbol.iterator]
, который при вызове возвращает другой объект итератора.
Итак, подведем итог:
- Вызовите метод, который возвращает итерируемый
- Итерируемый - это объект, имеющий свойство
[Symbol.iterator]
и доступ к данным исходного объекта. - Когда вы вызываете функцию в этом свойстве
[Symbol.iterator]
, вы получаете итератор object. - Объект итератора содержит метод
.next()
, который получает каждый элемент в последовательности, и делает это, возвращая объект, подобный этому {value: x, done: false}
каждый раз, когда вы вызываете .next()
.
Вы можете пропустить шаг 1, и у вашего основного объекта будет свойство [Symbol.iterator]
. Это по сути становится вашей итерацией по умолчанию. Если вы сделаете:
for (let x of myObj) {
console.log(x);
}
, он получит доступ к myObj[Symbol.iterator]()
, чтобы получить итератор. Но если вы хотите иметь более одного способа итерации вашей коллекции, то вы создаете отдельные функции, каждая из которых возвращает свою собственную итерацию (свой собственный объект со своим собственным свойством [Symbol.iterator]
).
В массиве у вас есть .entries()
и .values()
как пример двух методов, которые возвращают разные итерации, которые делают разные итераторы.
let x = ['a', 'b', 'c'];
for (let v of x.values()) {
console.log(v);
}
Это дает вывод:
'a'
'b'
'c'
Или, для .entries()
:
let x = ['a', 'b', 'c'];
for (let v of x.entries()) {
console.log(v);
}
[0, "a"]
[1, "b"]
[2, "c"]
Итак, каждый из .values()
и .entries()
возвращает разные объекты, каждый из которых имеет различный [Symbol.iterator]
, который при вызове в качестве функции возвращает другая функция итератора для их уникальной последовательности.
И, в случае массива, .values()
возвращает функцию, которая при вызове дает вам точно такой же итератор, что и просто итерация массива напрямую (например, * 1062) * свойство самого массива).
Теперь для вашей конкретной c ситуации
Вы хотите создать два метода, скажем, .forward()
и .backward()
что каждый создает объект остроумие ха [Symbol.iterator]
свойство, которое является функцией, которая при вызове возвращает свой уникальный объект итератора.
Таким образом, obj.forward()
вернет объект со свойством [Symbol.iterator]
, которое является функцией, которая при вызове возвращает объект итератора с соответствующим свойством .next()
для итерации вперед и соответствующим начальным состоянием.
Итак, obj.backward()
вернет объект со свойством [Symbol.iterator]
, которое является функцией, которая при вызове возвращает объект итератора с соответствующее .next()
свойство для итерации в обратном направлении и соответствующее начальное состояние.
Вот пример использования массива:
class myArray extends Array {
forward() {
return this; // core object already has appropriate forward
// [Symbol.iterator] property, so we can use it
}
backward() {
return {
[Symbol.iterator]: () => {
let i = this.length - 1; // maintains state in closure
return {
next: () => { // get next item in iteration
if (i < 0) {
return {done: true};
} else {
return {value: this[i--], done: false};
}
}
}
}
}
}
}
let x = new myArray('a', 'b', 'c');
console.log("Forward using default iterator")
for (let v of x) {
console.log(v);
}
console.log("\nUsing .forward()")
for (let v of x.forward()) {
console.log(v);
}
console.log("\nUsing .backward()")
for (let v of x.backward()) {
console.log(v);
}