let array = [1, 2, 3];
let iteratorForArray = {};
iteratorForArray.next()
// {value: 1, done: false}
iteratorForArray.next()
// {value: 2, done: false}
iteratorForArray.next()
// {value: 3, done: false}
iteratorForArray.next()
// {value: undefined, done: true}
'use strict';
// an array is a built-in iterable
let numberArray = [1, 2, 3];
// Symbol.iterator is the special property that contains a function that returns an iterator
let it = numberArray[Symbol.iterator]();
// we can then use the iterator to manually iterate through the array's values
it.next(); // Object { value: 1, done: false }
it.next(); // Object { value: 2, done: false }
it.next(); // Object { value: 3, done: false }
it.next(); // // Object { value: undefined, done: true }
let stringArray = ['a', 'b', 'c'];
// the for...of loop consumes an iterable
for (let ch of stringArray) {
console.log(ch) // a b c
}
let strArray = ['a', 'b', 'c'];
strArray[Symbol.iterator] = function () {
let idx = 0,
collection = this,
len = this.length;
return {
next: function () {
if (idx < len) {
let value = collection[idx];
idx++;
return {
value: value + '!',
done: false
};
} else {
return {
value: undefined,
done: true
};
}
}
};
};
for (let ch of strArray) {
console.log(ch); // a! b! c!
}
// we declare a generator using an asterisk
function* myGenerator (n) {
// we yield values with the yield keyword
yield n;
n++;
// we can yield as many times as we want
// each yield is a "pause" in the generator function's execution
yield n;
}
/*
invoking a generator function returns an iterator!
we've passed in a value for the parameter "n", but
no other code in the generator has executed yet
*/
let myIterator = myGenerator(41);
// each call to next advances us to the next yield
let firstYield = myIterator.next();
console.log(firstYield.value); // 41
let secondYield = myIterator.next();
console.log(secondYield.value); //42
// because we can pause generators, it doesn't matter if they run forever
function* generateDoubles (initialValue) {
let x = initialValue;
while (true) {
x = yield x * 2;
}
/*
Something really cool is happening here!
We can yield on the right side of an assignment.
When we call .next on the iterator, we can pass in a value as a parameter.
That value will then be the value that gets assigned!
*/
}
let i = 1,
it = generateDoubles(1), // invoking the generator 'primes' it with the parameter value
two = it.next().value, // this first call to .next advances us to the yield
four = it.next(two).value, // each subsequent call picks up where the last yield left off!
eight = it.next(four).value;
/*
Each yield pauses the function and yields a value.
If the yield is in an assignment, it will also wait
to receive a value from outside as well!
*/
function getData (gen) {
gen.next();
return Promise
.resolve('data')
.then(data => gen.next(data));
}
function * asyncAwait () {
let data = yield;
console.log(data);
}
let gen = asyncAwait();
getData(gen);