JavaScript/生成器
外观
术语“生成器”指的是一种用于生成一系列“任何事物”的技术:数字、字符串、数据库查询行、数组元素、DOM 树节点等。
它用于通过将数据分成小块来避免任何内存超载。
要使用它们,您必须首先定义一个生成器函数[1]。此类函数用一个星号 *
表示,它直接位于关键字 function
后面,例如:function* myGenerator(){...}
。
当调用时,该函数不会立即运行。它只会在遇到第一个 yield
语句 **之前** 运行,并返回一个“生成器对象”。这个“生成器对象”提供了一个 next
方法。一次又一次地调用 next
会按顺序返回序列元素。这些元素是由生成器函数中遇到的每个 yield
产生的。
- 该脚本生成一个包含 4 个整数的序列。
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
- 每次
next()
调用不仅返回一个value
;还有一个布尔值done
。因此,您可以在循环中调用生成器。
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)
- 从数组、数据库请求或树遍历中生成。
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)
- 创建所有偶数的无限序列。
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, ...
}
生成器函数可以接收参数。在本例中,'pageSize' 定义了要返回的数组元素的数量。
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 }