typescript:使类对象可迭代

mdr*_*ndv 2 typescript

如何使Typescript对象可迭代?在Python 3中,我可以做到

class EndlessCounter:
    def __init__(self):
        self.count = 0

    def __iter__(self):
        return self

    def __next__(self):
        self.count += 1
        return self.count
Run Code Online (Sandbox Code Playgroud)

但是这段代码的Typescript等价物是什么?

谢谢!

TmT*_*ron 18

接受的答案仅适用于单次迭代(因此它也不支持嵌套迭代),最糟糕的是当您尝试再次迭代时它将进入无限循环。

\n

这是修复这些问题的版本:

\n
class Counter implements Iterable<number> {\n    [Symbol.iterator]() {\n        let counter = 0;\n        return {\n            next: () => {\n                return {\n                    done: counter >= 5,\n                    value: counter++\n                }\n            }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 每当请求迭代器时,我们都会返回一个迭代器count=0
  • \n
  • 每次迭代都会增加闭包变量,counter直到完成
  • \n
\n

现在多次迭代工作:

\n
let c = new Counter();\nfor (let i of c) console.log(i);\nfor (let i of c) console.log(i);\n
Run Code Online (Sandbox Code Playgroud)\n

嵌套迭代也有效:

\n
let c = new Counter();\nfor (let i of c) {\n    console.log(\'OUTER\', i);\n    for (let i of c) {\n        console.log(\'--inner\', i);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

游乐场示例

\n

发电机功能

\n

另一种方法是使用生成器函数,该函数会生成更短的代码(请参阅Kriszti\xc3\xa1n Ballas 答案):

\n
class Counter implements Iterable<number> {\n    *[Symbol.iterator](): IterableIterator<number> {\n        let counter = 0;\n        while (counter < 5) {\n            yield counter++;\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

游乐场示例

\n


Nit*_*mer 10

Javascript支持迭代器和生成器,typescript不会增加太多:typescript Iterators和Generators.

你的代码可以在javascript中这样完成:

function* generator() {
    let counter = 0;
    while (true) {
        yield counter++;
    }
}

var iterator = generator();
console.log(iterator.next().value); // 0
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
Run Code Online (Sandbox Code Playgroud)

编辑

你可以用一个类做同样的事情:

class Counter implements Iterator<number> {
    private counter = 0;

    public next(): IteratorResult<number> {
        return {
            done: false,
            value: this.counter++
        }
    }
}

let c = new Counter();
console.log(c.next().value); // 0
console.log(c.next().value); // 1
console.log(c.next().value); // 2
Run Code Online (Sandbox Code Playgroud)

第二次编辑

使用生成器的第一个解决方案适用于for/of循环:

function* generator() {
    let counter = 0;
    while (counter < 5) {
        yield counter++;
    }
}
for (let i of generator()) console.log(i);
Run Code Online (Sandbox Code Playgroud)

但是,使用您需要执行的实例打印0到5:

class Counter implements Iterable<number> {
    private counter = 0;

    public [Symbol.iterator]() {
        return {
            next: function() {
                return {
                    done: this.counter === 5,
                    value: this.counter++
                }
            }.bind(this)
        }
    }
}
let c = new Counter();
for (let i of c) console.log(i);
Run Code Online (Sandbox Code Playgroud)

  • @NitzanTomer第二个编辑中的最后一个示例仍然不起作用。打字稿对此不支持。它给出一个错误,指出“ c不是数组或字符串类型”。有没有解决的办法? (2认同)
  • @sasidhar最后一个示例需要es6功能。如果用`-t es6`编译,它将很好用。 (2认同)

Jen*_*lly 6

假设您有一个包装字符串对象的简单类:

class StringWrapper {
    private readonly wrappedString: string;

    public constructor(str: string) {
        this.wrappedString = str;
    }

    *[Symbol.iterator](): IterableIterator<string> {
        for (let i = 0; i < this.wrappedString.length; ++i) {
            yield this.wrappedString[i];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

迭代器是一种生成器函数,它从包装的字符串中生成一个又一个字符。

现在你可以做这样的事情:

const wstr = new StringWrapper("abcd");

for (const char of wstr) {
    console.log(char); // will output "a", "b", "c", "d" separately
}

const anotherString == [..wstr]; // will be "abcd"
Run Code Online (Sandbox Code Playgroud)