-
Notifications
You must be signed in to change notification settings - Fork 16
generators and iterators
Функция-генератор объявляется с помощью ключевого слова function*
* - обязательный атрибут функции-генератора
С помощью функции-генератора создается объект-итератор
Функция-генератор определяет порядок итерирования данных,
который зависит от структуры данных
Сама по себе функция-генератор ничего не итерирует и ничего не возвращает,
кроме, как уже было сказано, объекта-итератора
Именно поэтому генератор
вместо оператора return
использует оператор yield
function* generator ( ... ) {
...
yield ...
}Оператор yield позволяет управлять работой итератора
Этим оператором функция-генератор говорит итератору,
что в этом месте нужно остановиться и вернуть текущее значение
function* colorsGenerator () {
while ( true ) {
yield `rgb(
${Math.round ( Math.random() * 255 )},
${Math.round ( Math.random() * 255 )},
${Math.round ( Math.random() * 255 )}
)`
}
}
let colorIterator = colorsGenerator ()
for ( var x=0; x < 100; x++ ) {
let point = document.body.appendChild (
document.createElement ( 'div' )
)
point.style = `
float: left;
width: 10px;
height: 10px;
background-color: ${ colorIterator.next().value};
`
}У объекта-итератора есть обязательный метод next()
С помощью этого метода итератор переходит от текущего элемента структуры данных к следующему
Этот метод возвращает объект с двумя свойствами: value и done
✅ Свойство value содержит текущий элемент структуры данных
✅ Свойство done принимает значение true, когда процесс итерирования структуры данных завершен
Собственно говоря, алгоритм работы итератора описывается в генераторе
Вот так "рождается" итератор со встроенным алгоритмом итерирования массива данных
var iterator = generator ( ... )☕ 1️⃣
var user = {
login: "Сергей",
avatar: "https://www.shareicon.net/data/2015/12/14/207817_face_300x300.png",
email: "serg789@gmail.com",
place ( tagName ) {
return document.body.appendChild (
document.createElement ( tagName )
)
},
showAvatar () {
let ava = this.place ( "img" )
ava.src = this.avatar
ava.width = "70"
return ava
},
showLogin () {
let x = this.place ( "h3" )
.innerHTML = this.login
return x
},
showEmail () {
let x = this.place ( "p" )
.innerHTML = this.email
return x
}
}
user.generator = function* () {
yield this.showLogin ()
yield this.showEmail ()
yield this.showAvatar ()
}
user.iterator = user.generator ()
while ( !user.iterator.next().done ) {}Если у объекта есть свойство Symbol.iterator, то этот объект является итерабельным
( то есть можно перебирать его свойства оператором for...of )
Symbol.iterator является ссылкой на функцию-генератор
user [ Symbol.iterator ] = function* () {
yield this.showLogin ()
yield this.showEmail ()
yield this.showAvatar ()
}for ( var x of user )
console.log ( `working...` )console.log ( ...user )function* someGenerator ( startValue, endValue ) {
var y = startValue
while ( y < endValue )
yield y += String.fromCharCode ( y.charCodeAt( y.length-1 ) + 1 )
}
var someIterator = someGenerator ( "a", "abcdef" )☕ 3️⃣ Асинхронный генератор
Создадим генератор, который выдает по одному символу в секунду из массива, переданного ему в качестве аргумента
async function* messageGenerator ( arr ) {
while ( arr.length > 0 ) {
var result = await new Promise (
function ( resolve ) {
setTimeout (
() => resolve ( arr.shift() ),
1000
)
}
)
yield result
}
}Поскольку протокол итерирования, заложенный в генераторе, возвращает промис на каждой итерации, для работы с ним объявим асинхронную функцию showMessage
showMessage создаст итератор с помощью генератора messageGenerator, передав ему строку, которая будет выводиться на страницу по одному символу в секунду
showMessage будет ждать ( await ), когда асинхронный итератор вернет очередное значение, и после этого выведет его на страницу
async function showMessage ( message ) {
const iterator = messageGenerator ( [...message] )
let finish = false
while ( !finish ) {
let currentState = await iterator.next()
document.body.innerText += !currentState.done ?
currentState.value : ""
finish = currentState.done
}
}Вызовем асинхронную функцию showMessage:
showMessage ( "Привет, студент!" )☕ 4️⃣
function* someGenerator ( objs ) {
var currentItem = objs [ 0 ]
var nextItem = objs [ 0 ]
while ( !!nextItem ) {
currentItem = nextItem
nextItem = !!currentItem.nextItem ?
objs.find ( x => currentItem.nextItem === x.val )
: null
yield currentItem.val
}
}
var objects = [
{ val: "first", nextItem: "second" },
{ val: "forth", nextItem: "fifth" },
{ val: "sixth", nextItem: null },
{ val: "third", nextItem: "forth" },
{ val: "fifth", nextItem: "sixth" },
{ val: "second", nextItem: "third" }
]
var iterator = someGenerator ( objects )☕ 5️⃣
function* elemsGenerator ( elemsProps ) {
for ( let elemData of elemsProps ) {
yield ( elem => {
var el = document.createElement ( elem.tagName )
document.body.appendChild ( el )
if ( elem.attrs )
for ( var x in elem.attrs ) {
el [ x ] = elem.attrs [ x ]
}
return el
})( elemData )
}
}
var elems = [
{ tagName: "div", attrs: { id: "first", className: "first" } },
{ tagName: "article", attrs: { id: "second", className: "second" } },
{ tagName: "figure", attrs: { id: "third", className: "third" } },
{ tagName: "p", attrs: { id: "forth", className: "forth" } }
]
var newElement = elemsGenerator ( elems )☕ 6️⃣
let btn = document.body.appendChild (
document.createElement ( "button" )
)
btn.innerText = "new"
btn.onclick = function ( event ) {
let ava = getAvatar.next()
if ( !ava.done ) document.body.appendChild ( ava.value )
}
function* avaGenerator () {
let num = 9
while ( ++num < 99 ) {
let ava = document.createElement ( "img" )
ava.src = `https://www.shareicon.net/data/2015/12/14/2078${num}_face_300x300.png`
ava.width = "80"
yield ava
}
}
let getAvatar = avaGenerator ()
© Irina H.Fylyppova 2018
Использование данных материалов или любой их части коммерческими школами ( курсами ) является нарушением авторских прав
| 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 |
| ⏬ |
|---|
- Блок-схема алгоритма
- Developer Tools
- Chrome DevTools
- Переменные
- Оператор typeof
- Структуры данных
- Операторы присваивания
- Логические выражения
- Условные операторы
- Инкремент
- Свойство length
- Оператор цикла for
- UTF-8
Homework
- Приведение типов
- NaN | null | Infinity
- BigInt (ES10)
- Функции
- Методы
- Методы строк
- Методы массивов
- Date ()
Самостоятельная работа
Практика (XSS)
Homework
- Циклы while и do...while
- Циклы for...of и for...in
- Параметры по умолчанию
- Объект function
Практика
Homework
- Нативные и host-объекты
- Литерал объекта
- Унаследованные свойства
- Конструктор
- Модель наследования
- Публичные и приватные свойства
- Оператор in
1
Homework
- Итерирующие методы массивов
- Тестирование производительности
- SHA
Homework
- Размеры и прокрутка элемента
- Event Loop
- async | await
- API
- REST | HATEOAS
- status codes
JSON placeholder-
JSON server
fake chat
Homework
- strict mode
- Вычисляемые имена свойств
- Краткий синтаксис методов
- Краткий литерал объекта
- Классы
Homework
- :not(:defined)
- Shadow DOM
- Custom elements
- Lifecycle hooks
- whenDefined
- <template>
- slot
1
2
3
Homework
- npm
- webpack
Упражнение 1- ES6 модули
Упражнение 2- --mode | --watch
Упражнение 3
Упражнение 4
Упражнение 5
Упражнение 6
Упражнение 7
Упражнение 8
Homework
| ⏫ |
|---|

Дополнительно
Справочная инфо
Git Bush
TCP/IP
Коды символов