跳转到内容

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 }

参考资料

[编辑 | 编辑源代码]
华夏公益教科书