2016-04-11 5 views
3

В ECMAScript6 iterator - объект с методом next(), который возвращает объект с двумя свойствами: {value, done}. Например .:Почему нам нужны итерационные и итераторные концепции?

function createIterator(ra) { 
    let i = 0; 
    return { 
     next() { 
      if (i < ra.length) 
       return {value: ra[i++], 
         done: false}; 
      else 
       return {value: undefined, 
         done: true}; 
     } 
    }; 
} 

Создав итератор один находит это не очень полезно в своем собственном праве, как нет встроенного синтаксиса, чтобы воспользоваться итератора. Вместо этого нужно делать такие вещи, как:

const it = createIterator(['a', 'b', 'c']); 
    while (true) { 
     const o = it.next(); 
     if (o.done) 
      break; 
     else 
      console.log(o.value); 
    } 

«Iterable» с другой стороны, является объектом с Symbol.iterator собственности, которая должна быть функция без аргументов, который возвращает итератор:

function createIterable(ra) { 
    let it = createIterator(ra); 
    return { 
     [Symbol.iterator]() {return it;} 
    }; 
} 

... и когда мы создаем итератор мы наконец-то сможем использовать for of синтаксис:

for (let v of createIterable(['a', 'b', 'c'])) 
    console.log(v); 

Глядя на приведенный выше код на добавленную стоимость «Iterable» объекта над «итератором» нелегко воспринимается. Итак, зачем Javascript нужны эти две отдельные концепции итератора итератора? Кстати, это то, что Java does as well, поэтому должна быть какая-то независимая от языка причина, почему это хорошая идея иметь эти две разные концепции.

+0

Итератор должен использовать 'yield', а не' return'. Итераторы реализуют ленивую оценку, например, генераторы Python и, да, Java. Итераторы - это просто способ стандартизировать, как вы перебираете объекты - это происходит из C++, где итераторы предназначены для стандартизации итерации по объектам, где неясно, к чему перебирать. Там есть мир разницы. –

+1

Понятно, что «итератор» обертывает текущее состояние операции итерации, а «итерируемый» символ отмечает коллекцию как способную обеспечить итератор. – Alnitak

+0

@ Итераторы и итераторы AkshatMahajan стоят само по себе. Генераторы (в этом отношении) просто удобны. –

ответ

2

Концептуально объект, реализующий интерфейс «итератор», просто инкапсулирует текущее состояние операции итерации. Как только этот итератор потребляется (it.done === true), он не может быть повторно использован.

Функция «итерабельного» возвращает новый итератор при каждом его вызове.

В этом отношении будьте осторожны с функцией OP, которая является потенциально ошибочной, поскольку объект, созданный его функцией createIterable, допускает только одноразовый вызов его функции Symbol.iterator. Он не сработает, если возвращенный объект был передан более чем одной операции for .. of. В идеале следует читать:

function createIterable(ra) { 
    return { 
     [Symbol.iterator]() { 
      return createIterator(ra); 
     } 
    } 
} 
+0

@MarcusJuniusBrutus Я восстановил мое предостережение - ваша функция 'createIterable' должна работать так, чтобы возвращаемый« итерируемый »объект можно было повторно использовать. – Alnitak

+1

Да, сейчас хорошо. Я оставляю ошибку в моем вопросе, поскольку это оправдывает будущее будущих читателей, поскольку ваше предостережение является решающим и служит для выделения разделения труда между итерируемым итератором. –

+0

@MarcusJuniusBrutus Я сбитый с толку - не понял, что вы были OP! :п – Alnitak

Смежные вопросы