В чем смысл * [Symbol.iterator] в этом контексте
Я нашел код в Интернете. Я раздавил исходный код в этот небольшой отрывок, который при запуске напечатает 1-20 на консоли.
var NumbersFromOne = {
*[Symbol.iterator] () {
for (let i = 1;; ++i) yield i;
}
};
var take = function* (numberToTake, iterable) {
let remaining = numberToTake;
for (let value of NumbersFromOne) {
if (remaining-- <= 0) break;
yield value;
}
}
var printToTwenty = take(20, NumbersFromOne)
console.log(...printToTwenty);
Теперь я понимаю, что take() - это функция GeneratorFunction.
Когда вызывается take(), ему присваивается итератор.
Код "... printToTwenty" использует оператор спреда для итерации через эту функцию.
Я понимаю, что NumbersFromOne является объектом. Я пришел сюда, чтобы узнать, что означает эта часть:
*[Symbol.iterator] () {}
Объявление функций генератора выполняется следующим образом: function *() {}
Поэтому я предполагаю, что это не объявление функции генератора.
* также не является именем функции
* также не может быть заменен другим оператором (/, -, +)
Что такое сделка с этим синтаксисом, и почему это * перед [Symbol.iterator]
Если после этого он не будет запущен.
Я считал, что * [Symbol.iterator]() - это способ переписать существующее свойство итератора, но тогда он не сказал бы это [Symbol.iterator].
Благодарю!
Ответы
Ответ 1
Есть несколько вещей, которые могут сделать этот код сложным:
Он использует сокращенное обозначение свойства объекта. То, что вы видите здесь, на самом деле следующее:
var NumbersFromOne = {
[Symbol.iterator]: function* () {
for (let i = 1;; ++i) yield i;
}
};
Symbol.iterator
создает пользовательский итератор для объекта NumbersFromOne
.
Таким образом, ваш код в основном означает, что итератор NumbersFromOne
определяется как генератор. Вместо того, чтобы вручную определять функцию, которая возвращает следующие и другие свойства:
var NumbersFromOne = {
[Symbol.iterator]: function () {
var i = 1;
return {
next: function() {
return { value: i++, done: false };
}
};
}
};
Возврат генератора автоматически создает для вас next
функцию и позволяет вам уступить, когда вам нужно.
Затем его можно назвать:
const it = NumbersFromOne[Symbol.iterator]();
it.next(); // 1
it.next(); // 2
it.next(); // 3
// ...
Примечание: Написанный таким образом, этот итератор никогда не заканчивается, так что если вы должны были назвать его в for... of
цикла без конечного состояния, было бы заморозить программу.