Skip to content

Itreable

Iteratable是实现了 The iterable protocol(可迭代协议)的对象。Iteratable必需实现一个[Symbol.iterator](): Iterator<T>方法,实现了这个方法,就可以在需要迭代的地方,比如for...ofArray.fromnew Set()等使用该对象。Iteratable定义如下:

ts
interface Iterable<T> {
  [Symbol.iterator](): Iterator<T>;
}

以下为示例,MakeRange会返回指定范围内的整数,比如new MakeRage(0, 10)会返回0,1,2,3...,9

ts
class MakeRange implements Iterable<number> {
  private _first: number;
  private _last: number;

  constructor(first, last) {
    this._first = first;
    this._last = last;
  }

  [Symbol.iterator](): Iterator<number> {
    return new RangeIterator(this._first, this._last);
  }
}

class RangeIterator implements Iterator<number> {
  private _first: number;
  private _last: number;

  constructor(first, last) {
    this._first = first;
    this._last = last;
  }

  next(value?: any): IteratorResult<number> {
    return {
      value: this._first++,
      done: this._first >= this._last,
    };
  }
}

Iterator

[Symbol.iterator]方法要求返回值是一个IteratorIterator是实现了 The iterator protocol(迭代器协议)的对象。Iterator定义如下:

ts
interface Iterator<T, TReturn = any, TNext = undefined> {
  // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
  next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
  return?(value?: TReturn): IteratorResult<T, TReturn>;
  throw?(e?: any): IteratorResult<T, TReturn>;
}

对象中必需包含一个next方法,方法中须返回一个另一个对象IteratorResult,其中包含valuedone两个属性,外部使用迭代器时,每次会调用next方法,返回对象中的value表示此次迭代的值,done表示迭代是否完成,返回true表示已经完成迭代。示例如下:

ts
class RangeIterator implements Iterator<number> {
  private _first: number;
  private _last: number;

  constructor(first, last) {
    this._first = first;
    this._last = last;
  }

  next(value?: any): IteratorResult<number> {
    return {
      value: this._first++,
      done: this._first >= this._last,
    };
  }
}

实现Iterable协议的对象就可以通过for...of等方式来遍历了:

ts
for (const n of new MakeRange(0, 10)) {
  console.log(n);
}
// 0,1,2...,9

IterableIterator

另外,还存在一个IterableIterator类,它集IterableIterator于一身,换句话说,它需要同时定义[Symbol.iterator]()方法和next方法。

ts
interface IterableIterator<T> extends Iterator<T> {
  [Symbol.iterator](): IterableIterator<T>;
}

它的好处是只需要定义一个对象即可实现一个可迭代的对象,从而减少冗余代码(由于 TypeScript 类型推断的能力,代码省去了一些显示地类型说明):

ts
class MakeRange {
  private _first: number;
  private _last: number;

  constructor(first, last) {
    this._first = first;
    this._last = last;
  }

  [Symbol.iterator]() {
    return this;
  }

  next() {
    return {
      value: this._first++,
      done: this._first >= this._last,
    };
  }
}

值得一提的是,很多接口,比如Array.values,返回值类型正是IterableIterator

参考资料