Сборка от 17 марта 2017 г



Download 9,9 Mb.
bet282/349
Sana26.04.2022
Hajmi9,9 Mb.
#582433
TuriУчебник
1   ...   278   279   280   281   282   283   284   285   ...   349
Bog'liq
ilja kantor sovremennyj uchebnik-1chast PdfToWord

Генератор – итератор


Как вы, наверно, уже догадались по наличию метода next() , генератор связан с итераторами. В частности, он является итерируемым объектом. Его можно перебирать и через for..of :


function* generateSequence() { yield 1;


yield 2;
return 3;
}
let generator = generateSequence(); for(let value of generator) {
alert(value); // 1, затем 2
}

Заметим, однако, существенную особенность такого перебора!


При запуске примера выше будет выведено значение 1 , затем 2 . Значение 3 выведено не будет. Это потому что стандартный перебор итератора игнорирует value на последнем значении, при done: true . Так что результат return в цикле for..of не выводится.


Соответственно, если мы хотим, чтобы все значения возвращались при переборе через for..of , то надо возвращать их через yield :

function* generateSequence() { yield 1;


yield 2; yield 3;
}
let generator = generateSequence(); for(let value of generator) {
alert(value); // 1, затем 2, затем 3
}

…А зачем вообще return при таком раскладе, если его результат игнорируется? Он тоже нужен, но в других ситуациях. Перебор через for..of – в некотором смысле «исключение». Как мы увидим дальше, в других контекстах return очень даже востребован.




Композиция генераторов


Один генератор может включать в себя другие. Это называется композицией. Разберём композицию на примере.


Пусть у нас есть функция generateSequence , которая генерирует последовательность чисел:

function* generateSequence(start, end) {


for (let i = start; i <= end; i++) { yield i;


}

}


// Используем оператор … для преобразования итерируемого объекта в массив let sequence = [...generateSequence(2,5)];

alert(sequence); // 2, 3, 4, 5


Мы хотим на её основе сделать другую функцию generateAlphaNumCodes() , которая будет генерировать коды для буквенно‑цифровых символов латинского алфавита:



  • 48..57 – для 0..9

  • 65..90 – для A..Z

  • 97..122 – для a..z

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


Естественно, раз в нашем распоряжении есть готовый генератор generateSequence , то хорошо бы его использовать.

Конечно, можно внутри generateAlphaNum запустить несколько раз generateSequence , объединить результаты и вернуть. Так мы бы сделали с обычными функциями. Но композиция – это кое‑что получше.


Она выглядит так:

function* generateSequence(start, end) {


for (let i = start; i <= end; i++) yield i;
}


function* generateAlphaNum() {
// 0..9
yield* generateSequence(48, 57);

// A..Z
yield* generateSequence(65, 90);


// a..z
yield* generateSequence(97, 122);


}


let str = '';

for(let code of generateAlphaNum()) { str += String.fromCharCode(code);


}

alert(str); // 0..9A..Za..z


Здесь использована специальная форма yield* . Она применима только к другому генератору и делегирует ему выполнение.


То есть, при yield* интерпретатор переходит внутрь генератора‑аргумента, к примеру, generateSequence(48, 57) , выполняет его, и все yield , которые он делает, выходят из внешнего генератора.


Получается – как будто мы вставили код внутреннего генератора во внешний напрямую, вот так:

function* generateSequence(start, end) {


for (let i = start; i <= end; i++) yield i;
}


function* generateAlphaNum() {
// yield* generateSequence(48, 57); for (let i = 48; i <= 57; i++) yield i;

// yield* generateSequence(65, 90); for (let i = 65; i <= 90; i++) yield i;


// yield* generateSequence(97, 122); for (let i = 97; i <= 122; i++) yield i;


}


let str = '';

for(let code of generateAlphaNum()) { str += String.fromCharCode(code);


}

alert(str); // 0..9A..Za..z


Код выше по поведению полностью идентичен варианту с yield* . При этом, конечно, переменные вложенного генератора не попадают во внешний,


«делегирование» только выводит результаты yield во внешний поток.

Композиция – это естественное встраивание одного генератора в поток другого. При композиции значения из вложенного генератора выдаются «по мере готовности». Поэтому она будет работать даже если поток данных из вложенного генератора оказался бесконечным или ожидает какого‑либо условия для завершения.





Download 9,9 Mb.

Do'stlaringiz bilan baham:
1   ...   278   279   280   281   282   283   284   285   ...   349




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish