Является ли итерация такой же, как итератор, или они разные?
Из спецификаций кажется, что итеративный объект - это, скажем, obj
такой объект, который obj[Symbol.iterator]
ссылается на функцию, поэтому при вызове возвращает объект, у которого есть next
метод, который может вернуть {value: ___, done: ___}
объект:
function foo() {
let i = 0;
const wah = {
next: function() {
if (i <= 2) return { value: (1 + 2 * i++), done: false }
else return { value: undefined, done: true }
}
};
return wah; // wah is iterator
}
let bar = {} // bar is iterable
bar[Symbol.iterator] = foo;
console.log([...bar]); // [1, 3, 5]
for (a of bar) console.log(a); // 1 3 5 (in three lines)
Таким образом, в приведенном выше коде bar
это итерация, wah
итератор, и next()
интерфейс итератора.
Итак, итерируемый и итератор это разные вещи.
Теперь, однако, в общем примере генератора и итератора:
function* gen1() {
yield 1;
yield 3;
yield 5;
}
const iter1 = gen1();
console.log([...iter1]); // [1, 3, 5]
for (a of iter1) console.log(a); // nothing
const iter2 = gen1();
for (a of iter2) console.log(a); // 1 3 5 (in three lines)
console.log(iter1[Symbol.iterator]() === iter1); // true
В приведенном выше случае gen1
это генератор, iter1
итератор, и он iter1.next()
будет выполнять свою работу правильно. Но iter1[Symbol.iterator]
дает функцию, которая при вызове возвращает iter1
, которая является итератором. Так iter1
и в этом случае итеративный и итератор?
Кроме того, iter1
он отличается от приведенного выше примера 1, поскольку итерация в примере 1 может давать [1, 3, 5]
столько раз, сколько требуется [...bar]
при использовании , в то время как iter1
она является итеративной, но поскольку она возвращает себя, то есть каждый раз [1, 3, 5]
один и тот же итератор дает только один раз.
Таким образом, мы можем сказать, для повторения bar
, сколько раз может [...bar]
дать результат [1, 3, 5]
- и ответ, это зависит. И повторяется ли итератор? И ответ таков: это разные вещи, но они могут быть одинаковыми, когда итерируемый использует себя в качестве итератора. Это верно?
источник
iter1
и в этом случае и итеративный и итератор? » - да. Все нативные итераторы также итерируемы, возвращая себя, так что вы можете легко передать их в конструкции, которые ожидают итерацию.Ответы:
Да, итерируемыми и итераторы разные вещи, но большинство итераторы ( в том числе все те , которые вы получаете от самого JavaScript, например, из
keys
илиvalues
методов наArray.prototype
или генераторов из функций генератора) наследуются от % IteratorPrototype% объекта , который имеетSymbol.iterator
метод , как это:В результате все стандартные итераторы также являются итеративными. Это значит, что вы можете использовать их напрямую или использовать их в
for-of
циклах и т. Д. (Которые ожидают итераторов, а не итераторов).Рассмотрим
keys
метод массивов: он возвращает итератор массива, который посещает ключи массива (его индексы в виде чисел). Обратите внимание, что он возвращает итератор . Но общее использование этого:for-of
принимает итеративный , а не итератор , так почему это работает?Это работает, потому что итератор также итеративен;
Symbol.iterator
просто возвращаетсяthis
.Вот пример, который я использую в главе 6 моей книги: если вы хотите перебрать все записи, но пропустить первую и не хотите использовать
slice
для вырезания подмножества, вы можете получить итератор, прочитать первое значение, затем передать вfor-of
цикл:Обратите внимание, что это все стандартные итераторы. Иногда люди показывают примеры кодированных вручную итераторов, например:
Показать фрагмент кода
Итератор, возвращаемый
range
там, не является итеративным, поэтому он перестает работать, когда мы пытаемся использовать его сfor-of
.Чтобы сделать его итеративным, нам нужно:
Symbol.iterator
метод в начале ответа выше илиК сожалению, TC39 решил не предоставлять прямой способ получения объекта% IteratorPrototype%. Есть косвенный путь (получение итератора из массива, затем взятие его прототипа, который определен как% IteratorPrototype%), но это боль.
Но в любом случае нет необходимости писать итераторы подобным образом; просто используйте функцию генератора, поскольку возвращаемый генератор является итеративным:
Показать фрагмент кода
Напротив, не все итерации являются итераторами. Массивы являются итеративными, но не итераторами. Как и строки, карты и наборы.
источник
Я обнаружил, что есть некоторые более точные определения терминов, и это более точные ответы:
Согласно спецификации ES6 и MDN :
Когда у нас
foo
называется функцией генератора . И тогда, когда у нас естьbar
является генератором объекта . И объект генератора соответствует и итерируемому протоколу и протоколу итератора .Более простой версией является интерфейс итератора, который является всего лишь
.next()
методом.Итерация протокол: для объекта
obj
,obj[Symbol.iterator]
дает «ноль аргументы функцию , которая возвращает объект, в соответствии с протоколом итератора».Судя по названию ссылки MDN , мы также можем просто назвать объект генератора «генератором».
Обратите внимание, что в книге Николаса Закаса «Понимание ECMAScript 6» он вероятно назвал «функцию генератора» «генератором», а «объект генератора» - «итератором». Вывод заключается в том, что они на самом деле оба связаны с «генератором» - один является функцией генератора, а другой - объектом-генератором или генератором. Объект генератора соответствует как итерируемому протоколу, так и протоколу итератора.
Если это просто объект, соответствующий протоколу итератора , вы не можете использовать
[...iter]
илиfor (a of iter)
. Это должен быть объект, который соответствует итерируемому протоколу.И еще, есть еще один класс Iterator, в будущих спецификациях JavaScript, который все еще находится в черновике . Она имеет больший интерфейс, включая методы , такие как
forEach
,map
,reduce
из текущего интерфейса массива, а также новых, таких , как иtake
, иdrop
. Текущий итератор ссылается на объект только сnext
интерфейсом.Чтобы ответить на первоначальный вопрос: в чем разница между итератором и итерируемым, ответ таков: итератор - это объект с интерфейсом
.next()
, а итератор - этоobj
такой объект , которыйobj[Symbol.iterator]
может дать функцию с нулевым аргументом, которая при вызове возвращает итератор.И генератор является и итеративным и итератором, чтобы добавить к этому.
источник