В чем смысл * [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 цикла без конечного состояния, было бы заморозить программу.