关于 JS 迭代器和生成器(About JS iterators and generators)

迭代器(MDN):在JS中,它会定义一个序列,并在终止时可能返回一个返回值(如果value和done一起存在,则它是迭代器的返回值),迭代器通过使用 next() 方法实现迭代协议的任何一个对象。其中,最常见的迭代器是Array迭代器。

调用 iterator.next() 会返回:{ value: unknown, done: boolean }

// 一个范围迭代器工具示例

function make_range_iterator(start = 0, end = Number.POSITIVE_INFINITY, step = 1) {
    let next_idx = start;
    let iteration_cnt = 0;

    const range_iterator = {
        next() {
          let result;
          if (next_idx <= end) {
            result = {
              value: next_idx,
              done: false,
            };
            next_idx += step;
            iteration_cnt += 1;
      
            return result;
          }
      
          return {
            value: iteration_cnt,
            done: true,
          };
        },
    };

    return range_iterator;
}

const it = make_range_iterator(1, 5);

let cur_val = it.next();
while (!cur_val.done) {
  console.log(cur_val.value); // 1, 2, 3, 4, 5
  cur_val = it.next();
} 

生成器(MDN):考虑到自定义迭代器成本是比较高的,且需要显式地维护其内部状态。在需要使用迭代器的场景中,我们可以考虑使用生成器函数去产出一种被称为Generator的迭代器。

function* make_range_iterator_by_gen(start = 0, end = Number.POSITIVE_INFINITY, step = 1) {
    for (let i = start; i <= end; i += step) yield i;
}

const g = make_range_iterator_by_gen(1, 5);
let cur_val = g.next();
while (!cur_val.done) {
    console.log(cur_val.value); // 1, 2, 3, 4, 5
    cur_val = g.next();
}
console.log(cur_val); // { value: undefined, done: true }

// 补充中…

————————

< strong > iterator < / strong > (MDN): in JS, it defines a sequence and may return a return value at termination (if value and done exist together, it is the return value of the iterator). The iterator implements any object of the iteration protocol by using the next () method. The most common iterator is the array iterator.

调用 iterator.next() 会返回:{ value: unknown, done: boolean }

// 一个范围迭代器工具示例

function make_range_iterator(start = 0, end = Number.POSITIVE_INFINITY, step = 1) {
    let next_idx = start;
    let iteration_cnt = 0;

    const range_iterator = {
        next() {
          let result;
          if (next_idx <= end) {
            result = {
              value: next_idx,
              done: false,
            };
            next_idx += step;
            iteration_cnt += 1;
      
            return result;
          }
      
          return {
            value: iteration_cnt,
            done: true,
          };
        },
    };

    return range_iterator;
}

const it = make_range_iterator(1, 5);

let cur_val = it.next();
while (!cur_val.done) {
  console.log(cur_val.value); // 1, 2, 3, 4, 5
  cur_val = it.next();
} 

< strong > generator < / strong > (MDN): considering that the cost of a custom iterator is relatively high and its internal state needs to be explicitly maintained. In scenarios where iterators are needed, we can consider using generator functions to produce an iterator called generator.

function* make_range_iterator_by_gen(start = 0, end = Number.POSITIVE_INFINITY, step = 1) {
    for (let i = start; i <= end; i += step) yield i;
}

const g = make_range_iterator_by_gen(1, 5);
let cur_val = g.next();
while (!cur_val.done) {
    console.log(cur_val.value); // 1, 2, 3, 4, 5
    cur_val = g.next();
}
console.log(cur_val); // { value: undefined, done: true }

//In addition