原创 TypeScript入门教程 之  迭代器

原创 TypeScript入门教程 之 迭代器

 

Iterator

Iterator本身不是TypeScript或ES6功能,Iterator是面向对象的编程语言所通用的行为设计模式。通常,它是一个实现以下接口的对象:

 

interface Iterator<T> {
    next(value?: any): IteratorResult<T>;
    return?(value?: any): IteratorResult<T>;
    throw?(e?: any): IteratorResult<T>;
}

有关该<T>符号的更多信息,请参见后面的内容。
此接口允许从属于该对象的某个集合或序列中检索值。

 

IteratorResult

IteratorResult是一个简单的valuedone对:

interface IteratorResult<T> {
    done: boolean;
    value: T;
}

 

Iterator接口使用示例

想象有一个框架的对象,其中包括该框架所组成的组件的列表。使用Iterator接口,可以从该框架对象中检索组件,如下所示:

class Component {
  constructor (public name: string) {}
}

class Frame implements Iterator<Component> {

  private pointer = 0;

  constructor(public name: string, public components: Component[]) {}

  public next(): IteratorResult<Component> {
    if (this.pointer < this.components.length) {
      return {
        done: false,
        value: this.components[this.pointer++]
      }
    } else {
      return {
        done: true,
        value: null
      }
    }
  }

}

let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]);
let iteratorResult1 = frame.next(); //{ done: false, value: Component { name: 'top' } }
let iteratorResult2 = frame.next(); //{ done: false, value: Component { name: 'bottom' } }
let iteratorResult3 = frame.next(); //{ done: false, value: Component { name: 'left' } }
let iteratorResult4 = frame.next(); //{ done: false, value: Component { name: 'right' } }
let iteratorResult5 = frame.next(); //{ done: true, value: null }

//It is possible to access the value of iterator result via the value property:
let component = iteratorResult1.value; //Component { name: 'top' }

 

再次。Iterator本身不是TypeScript功能,该代码无需显式实现Iterator和IteratorResult接口就可以工作。但是,使用这些通用的ES6 接口来保持代码一致性非常有帮助。

 

好的,很好,但是可能会有所帮助。ES6定义了可迭代协议 ,symbol如果实现了可迭代接口,则该协议包括[Symbol.iterator] :

//...
class Frame implements Iterable<Component> {

  constructor(public name: string, public components: Component[]) {}

  [Symbol.iterator]() {
    let pointer = 0;
    let components = this.components;

    return {
      next(): IteratorResult<Component> {
        if (pointer < components.length) {
          return {
            done: false,
            value: components[pointer++]
          }
        } else {
          return {
            done: true,
            value: null
          }
        }
      }
    }
  }
}

let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]);
for (let cmp of frame) {
  console.log(cmp);
}

不幸的是frame.next(),这种模式无法使用,而且看起来有些笨拙。IterableIterator界面可以解救!

//...
class Frame implements IterableIterator<Component> {

  private pointer = 0;

  constructor(public name: string, public components: Component[]) {}

  public next(): IteratorResult<Component> {
    if (this.pointer < this.components.length) {
      return {
        done: false,
        value: this.components[this.pointer++]
      }
    } else {
      return {
        done: true,
        value: null
      }
    }
  }

  [Symbol.iterator](): IterableIterator<Component> {
    return this;
  }

}
//...

无论frame.next()for周期,现在做工精细用IterableIterator接口。

迭代器不必迭代有限的值。典型的例子是斐波那契数列:

class Fib implements IterableIterator<number> {

  protected fn1 = 0;
  protected fn2 = 1;

  constructor(protected maxValue?: number) {}

  public next(): IteratorResult<number> {
    var current = this.fn1;
    this.fn1 = this.fn2;
    this.fn2 = current + this.fn1;
    if (this.maxValue != null && current >= this.maxValue) {
      return {
        done: true,
        value: null
      } 
    } 
    return {
      done: false,
      value: current
    }
  }

  [Symbol.iterator](): IterableIterator<number> {
    return this;
  }

}

let fib = new Fib();

fib.next() //{ done: false, value: 0 }
fib.next() //{ done: false, value: 1 }
fib.next() //{ done: false, value: 1 }
fib.next() //{ done: false, value: 2 }
fib.next() //{ done: false, value: 3 }
fib.next() //{ done: false, value: 5 }

let fibMax50 = new Fib(50);
console.log(Array.from(fibMax50)); // [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

let fibMax21 = new Fib(21);
for(let num of fibMax21) {
  console.log(num); //Prints fibonacci sequence 0 to 21
}

使用迭代器为ES5目标构建代码

上面的代码示例需要ES6目标。但是,如果目标JS引擎支持,它也可以与ES5目标一起使用Symbol.iterator。这可以通过使用带有ES5目标的ES6库(将es6.d.ts添加到您的项目中)进行编译来实现。编译后的代码应在节点4 +,Google Chrome和其他一些浏览器中运行。

 

翻译来源:https://gitee.com/yunwisdoms/typescript-book/blob/master/docs/iterators.md

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值