可迭代对象

typeof obj[Symbol.iterator] == 'function'

Iterator协议-迭代器模式

interface $Interator {
  [Symbol.iterator](): object;
}
class IteratorObject implements $Interator {
  private data = {};
  private step = 0;
  private keys = [];
  constructor(data: object) {
    this.data = data;
    this.keys = Object.keys(data) as [];
  }
  public next() {
    let result { value: undefined, done: true };
    if(this.step < this.keys.length) {
      result = { value: this.data[this.keys[this.step]], done: false };
      this.step ++;
    }
    return result;
  }
  public [Symbol.iterator]() {
    return this;
  }
}

生成器

var x = 1;
function *foo() {
  x++;
  x = yield x++;
  console.log("x:", ++x);
  return x
}
let iterator = foo();
console.log(iterator.next());
console.log(iterator.next(3));
console.log(iterator.next());
  1. 执行foo()并没有执行生成器*foo(), 而只是构造了一个迭代器
  2. 第一个next启动了生成器, 并执行了第一行x++
  3. *foo()在yield语句处暂停, 并向next调用处返回{value: 2, done: false}, 此时*foo()处于暂停状态
  4. 第二个next恢复生成器执行第4行, 打印出{value: 4, done: true}

原理UML类图

generators

具体实现

main.js
let { userFunc } = require("./userFunc")
let { generator } = require("./generator")
function main() {
  let gen$ = generator(userFunc);
  let iterator = gen$();
  console.log(iterator.next());
}
main();
userFunc.js
function userFunc(_context) {
  var str;
  return function() {
    while(1) {
      switch((_context.pre = _context.next)) {
        case 0:
          _context.next = 1;
          return "hello";
        case 1:
          str = _context.arg;
          console.log(str);
          _context.next = 3;
          return "world";
        case 3:
          return _context.complete("return", "ending");
        case "end":
          return _context.stop();
      }
    }
  }
}
exports.userFunc = userFunc
generator.js
let { invoker } = require("./invoker");
let { Context } = require("./context");
let { Iterator } = require("./iterator");
function generator(userFunc) {
  return function() {
    let context = new Context()
    let generatorInvoker = invoker(userFunc, context)
    return Iterator(generatorInvoker, context)
  }
}
exports.generator = generator
context.js
class Context {
  done = false
  value = undefined
  next = 0;
  complete(type, result) {
    if(type === "return") {
      this.value = result;
      this.next = "end";
    }
    return null;
  }
  stop() {
    this.done = true;
    return this.value
  }
}
exports.Context=Context
invoker.js
function invoker(userFunc, context) {
  // 状态设置为start
  var state = 'start'
  var userFunc$1 = userFunc(context);
  return function generatorInvoker(arg) {
    // 已完成
    if(state === "completed") {
      return { value:undefined, done: true}
    }
    context.arg = arg;
    // 执行中
    while(true) {
      let result = userFunc$1() // 执行下一步,并获取状态 switch 里面return的值
      // 判断是否已经执行完成
      state = context.done ? "completed" : "yield";
      if(result === null) {
        continue
      }
      return {
        value: result,
        done: context.done
      }
    }
  }
}
iterator.js
function Iterator(generatorInvoker, context) {
  return {
    next: (arg)=> {
      context.method = "next";
      return generatorInvoker(arg);
    },
    ['throw']: (arg)=> {
      context.method = "throw";
      generatorInvoker(arg);
    }
  }
}