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 }