Шрифт:
// Функция, возвращающая итератор;
function counter(start) {
let nextValue = Math.round(start); // Частная переменная итератора
return { next: function {
return nextValue++; }
}; // Вернуть итератор
}
let serialNumberGenerator = counter(1000);
let sn1 = serialNumberGenerator.next; // 1000
let sn2 = serialNumberGenerator.next; // 1001
При работе с конечными коллекциями метод
next
итератора возбуждают исключение Stoplteration
, когда в коллекции не остается значений для выполнения очередной итерации. Stoplteration
– это свойство глобального объекта в JavaScript 1.7. Его значением является обычный объект (без собственных свойств), зарезервированный специально для нужд завершения итераций. Обратите внимание, что Stoplteration
не является функцией-конструктором, таким как TypeErгог
или RangeError.
Ниже приводится пример метода rangelter,
возвращающего итератор, который выполняет итерации по целым числам в заданном диапазоне:
// Функция, возвращающая итератор диапазона целых чисел
function rangelter(first, last) {
let nextValue = Math.ceil(first);
return {
next: function {
if (nextValue > last) throw Stoplteration;
return nextValue++;
}
};
}
// Пример неудобной реализации итераций с помощью итератора диапазона,
let r = rangelter(1.5); // Получить объект-итератор
while(true) { // Теперь использовать его в цикле
try {
console.log(г.next); // Вызвать метод next итератора
catch(e) {
if (е == Stoplteration) break; // Завершить цикл по Stoplteration else throw e;
}
}
Обратите внимание, насколько неудобно использовать объект-итератор в цикле из-за необходимости явно обрабатывать исключение
Stoplteration
. Из-за этого неудобства итераторы редко используются на практике непосредственно. Чаще используются итерируемые объекты. Итерируемый объект представляет коллекцию значений, по которым можно выполнять итерации. Итерируемый объект должен определять метод с именем __iterator__
(с двумя символами подчеркивания в начале и в конце), возвращающий объект-итератор для коллекции. В JavaScript 1.7 в цикл
for/in
была добавлена возможность работы с итерируемыми объектами. Если значение справа от ключевого слова in является итерируемым объектом, то цикл for/in
автоматически вызовет его метод __iterator__,
чтобы получить объект-итератор. Затем он будет вызывать метод next
итератора, присваивать возвращаемое им значение переменной цикла и выполнять тело цикла. Цикл for/in
сам обрабатывает исключение Stoplteration
, и оно никогда не передается программному коду, выполняемому в цикле. Пример ниже определяет функцию range,
возвращающую итерируемый объект (а не итератор), который представляет диапазон целых чисел. Обратите внимание, насколько проще выглядит цикл for/in
при использовании итерируемого объекта диапазона по сравнению с циклом while
, в котором используется итератор диапазона.
// Вернуть объект, представляющий диапазон.
// Границы диапазона не изменяются
// и хранятся в замыкании.
// Диапазоны могут проверять вхождение, max;
// Возвращает итерируемый объект, представляющий диапазон чисел
function range(min,max) { return {
get min { return min; },
get max { return max; },
includes: function(x) {
return min <= x && x <= max;
},
toString: function { // Диапазоны имеют строковое представление,
return "[" + min + "," + max + "]";