生成器方法

第八章介绍了生成器,你已学会如何在对象字面量上定义一个生成器:只要在方法名称前附加一个星号(*)。这一语法对类同样有效,允许将任何方法变为一个生成器。此处有个范例:

class MyClass {

    *createIterator() {
        yield 1;
        yield 2;
        yield 3;
    }

}

let instance = new MyClass();
let iterator = instance.createIterator();

此代码创建了一个拥有 createIterator() 生成器的 MyClass 类。该方法返回了一个迭代器,它的值在生成器内部用硬编码提供。当你使用一个对象来表示值的集合、并要求能简单迭代这些值,那么生成器方法就非常有用。数组、SetMap 都拥有多个生成器方法,负责让开发者用多种方式来操作它们的项。

既然生成器方法很有用,那么在表示集合的自定义类中定义一个默认迭代器,那就更好。你可以使用 Symbol.iterator 来定义生成器方法,从而定义出类的默认迭代器,就像这样:

class Collection {

    constructor() {
        this.items = [];
    }

    *[Symbol.iterator]() {
        yield *this.items.values();
    }
}

var collection = new Collection();
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);

for (let x of collection) {
    console.log(x);
}

// Output:
// 1
// 2
// 3

此例为生成器方法使用了一个需计算名称,并将此方法委托到 this.items 数组的 values() 迭代器上。任意管理集合的类都包含一个默认迭代器,这是因为一些集合专用的操作都要求目标集合具有迭代器。现在,Collection 的任意实例都可以在 for-of 循环内被直接使用,也能配合扩展运算符使用。

当你想让方法与访问器属性在对象实例上出现时,把它们添加到类的原型上就会对此目的有帮助。而另一方面,若想让方法与访问器属性只存在于类自身,那么你就需要使用静态成员。