JavaScript/Generators
The term generator denotes a technique to generate a sequence of 'anything': numbers, strings, rows of database queries, elements of an array, nodes of a DOM tree, ...
It's used to avoid any memory overloading, by splitting the data in small chunks.
To use them, you must define a generator function[1] first. Such functions are notated with an asterisk *
directly behind the keyword function
, e.g., function* myGenerator(){...}
.
When called, the function will not run instantly. It only runs just before the first occurrence of a yield
statement and returns a 'Generator object'. This 'Generator object' offers a next
method. Calling next
again and again returns the sequence elements one after the next. The elements arise by each yield
that is reached within the generator function.
Examples
edit- The script generates a sequence of 4 integers.
function* fourInts() {
let int = 0;
while (int < 4) {
yield int; // each .next() receives the current value of 'int'
int++;
}
}
const gen = fourInts(); // creation
alert(gen.next().value); // 0
alert(gen.next().value); // 1
alert(gen.next().value); // 2
alert(gen.next().value); // 3
alert(gen.next().value); // undefined
- Every
next()
call returns not only avalue
; there is also a booleandone
. Hence you can call the generator in loops.
function* fourInts() {
let int = 0;
while (int < 4) {
yield int;
int++;
}
}
const gen = fourInts(); // creation
do {
const tmp = gen.next();
if (tmp.done) {
break;
} else {
alert(tmp.value); // 0, 1, 2, 3
}
} while (true)
- Generation out of an array, a database request, or a tree traversal.
function* arrayElements() {
// for simplicity, we use an array; database queries or tree traversals
// are more realistic.
const myArray = ["yellow", "green", "blue"];
for (const elem of myArray) {
yield elem;
}
}
const sequence = arrayElements(); // creation
do {
const tmp = sequence.next();
if (tmp.done) {
break;
} else {
alert(tmp.value); // "yellow", "green", "blue"
}
} while (true)
- Creation of the infinite sequence of all even numbers.
function* evenNumbers() {
for (let i = 0; true; i = i + 2) {
yield i;
}
}
const sequence = evenNumbers(); // creation
let i = 0;
while (i < 20) {
i = sequence.next().value;
alert(i); // 0, 2, 4, ...
}
Parameters
editThe generator function may receive parameters. In this example, the 'pageSize' defines the number of array elements to be returned.
function* pagination(arr, pageSize) {
for (let i = 0; i < arr.length; i = i + pageSize) {
yield arr.slice(i, i + pageSize);
}
}
const arr = [1, 2, 3, 4, 5, 6, 7]
const page = pagination(arr, 3);
alert (page.next().value); // { value: [1, 2, 3], done: false }
alert (page.next().value); // { value: [4, 5, 6], done: false }
alert (page.next().value); // { value: [7], done: false }
alert (page.next().value); // { value: undefined, done: true }