2016-05-02 4 views
9

Я нашел код в Интернете. Я раздавил исходный код в этот небольшой отрывок, который при запуске напечатает 1-20 на консоли.В чем смысл * [Symbol.iterator] в этом контексте

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]() {} 

Объявление функций генератора осуществляется следующим образом: функция *() {}
Таким образом, я предполагаю, что это не возможность объявления функция генератора.

* также не представляет имя функции
* также не может быть заменен другим оператором (/, -, +)

Что такое сделка с этим синтаксисом, и почему это * перед тем [Symbol.iterator]
Если после этого он не будет запущен.
Я считал, что * [Symbol.iterator]() - это способ переписать существующее свойство итератора, но тогда он не сказал бы это [Symbol.iterator].

Спасибо!

ответ

9

Есть несколько вещей, которые могли бы сделать этот код выглядеть сложным:

Он использует свойство объекта сокращенную нотацию. То, что вы видите здесь, на самом деле следующее:

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

+0

Мне нравится этот ответ. Я хочу отметить, что * должен прийти после функции. Я сделал jsfiddle, чтобы продемонстрировать: http://www.es6fiddle.net/inpoxsps/ Я не знал, что это короткая нотация. Благодарим вас за разъяснение. – Captainlonate

+0

Упс, моё плохо, спасибо, что указали это. У меня еще не было возможности написать все, что есть у многих реальных генераторов.Теперь он должен работать :) – nils

+0

Привет, Нилс. Зачем нужны два итератора здесь, возьмите & numbersfromone. Take кажется излишним, если вы можете просто получить диапазон в цифрах, не так ли? –