Skip to content
On this page

生成器 (Generator) 与迭代器 (Iterator)

迭代

迭代协议

规定了迭代与实现的逻辑

迭代器

具体的迭代实现逻辑

迭代对象

可被迭代的对象 - 实现了 [Symbol.iterator] 方法

迭代语句

for...in; 以原始插入的循序迭代对象的可枚举属性 for...of; 根据迭代对象的迭代器具体实现迭代对象数据

迭代器实现原理

[Symbol.iterator]

javascript
let arr = ["a", "b", "b"];
let obj = {
  a: 1,
  b: 2,
  c: 3,
};
obj[Symbol.iterator] = function () {
  // 迭代协议
  let values = Object.values(obj);
  let index = 0;
  return {
    next() {
      if (index >= values.length) {
        return {
          done: true, // done 代表循环是否完成,true 已完成 false 未完成
        };
      }
      return {
        done: false,
        value: values[index++],
      };
    },
  };
};
for (const iterator of obj) {
  console.log(iterator);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Generator 是一个特殊的函数,执行它会返回一个 Iterator 对象。 通过遍历迭代器, Generator函数运行后会返回一个遍历器对象,而不是普通函数的返回值。

terators 模拟

迭代器有一个 next 方法,每次执行的时候会返回一个对象 对象里面有两个属性,一个是 value 表示返回的值,还有就是布尔值 done, 表示是否迭代完成

js
function buy(books) {
    let i = 0;
    return {
        next(){
            let done = i == books.length;
            let value = !done ? books[i++] : undefined;
            return {
                value: value,
                done: done
            }
        }
    }
}

let iterators = buy(['js', 'html']);
var curr;
do {
    curr = iterators.next();
    console.log(curr);
} while (!curr.done);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Generator 函数

在形式上 Generator 是一个普通的函数,但是有两个特征。一是,function 命名与函数名之间有一个星号 二是,函数体内部使用 yield 语句,定义遍历器的每个成员,即不同的内部状态

Generator 语法

js
function* fn(){
	yield 1;
  yield 2;
  yield 3;
}
let g = gen();
1
2
3
4
5
6

生成器用于创建迭代器

js
function* buy(books){
    for(var i=0;i<books.length;i++){
        yield books[i];
    }
}
let buying = buy(['js','html']);
var curr;
do {
    curr = buying.next();
    console.log(curr);
} while (!curr.done);
1
2
3
4
5
6
7
8
9
10
11

自执行 Generator 函数

co 函数,自动化 generator 函数调用器 Generator 是一个特殊的函数,执行它会返回一个 Iterator 对象。通过遍历迭代器,Generator 函数运行后悔返回遍历器对象,而不是函数的返回值。

javascript
function* fn() {
  yield new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("a");
      resolve(1);
    }, 500);
  });
  yield new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("b");
      resolve(2);
    }, 500);
  });
  yield new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("c");
      resolve(3);
    }, 500);
  });
}
co(fn);
function co(fn) {
  let f = fn();
  next();
  function next(data) {
    let res = f.next();
    if (!res.done) {
      // 上一个异步走完了,在执行下一个异步
      res.value.then((info) => {
        console.log(info, data);
        // data 上一次的数据
        next(info);
      });
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
沪ICP备20006251号-1