TypeScript实战指南》—2.1.7 iterator和generator

网友投稿 578 2022-05-30

2.1.7 iterator和generator

1. iterator

当一个对象实现了Symbol.iterator时,我们认为它是可迭代的。如array、map、set、string、int32Array、uint32Array等一些内置的类型,目前都已经实现了各自的Symbol.iterator。对象上的Symbol.iterator函数负责返回供迭代的值。

for..of语句会遍历可迭代的对象,调用对象上的Symbol.iterator方法。

比如下面是在数组上使用for..of的例子:

const array = [233, "hello", true];

for (let value of array) {

console.log(value); // 233, "hello", true

}

for..of和for..in都可以迭代一个数组,但它们之间的区别很大。最明显的区别莫过于它们用于迭代器的返回值并不相同,for..in迭代的是对象的键,而for..of迭代的是对象的值。

我们可以从下面的例子中看出两者之间的区别:

const array = [3, 4, 5];

for (let i in array) {

console.log(i); // 0, 1, 2

}

for (let i of array) {

console.log(i); // 4, 5, 6

}

另一个区别在于,for..in可以操作任何对象,提供了查看对象属性的一种方法。但是for..of关注迭代对象的值,内置对象Map和Set已经实现了Symbol.iterator方法,让我们可以访问它们的值:

const fruits = new Set(["apple", "pear", "mango"]);

fruits["peach"] = "Princess Peach! Make a wish!";

for (let fruit in fruits) {

console.log(fruit); // "peach"

}

for (let fruit of fruits) {

console.log(fruit); // "apple", "pear", "peach"

}

但这样的特性仅仅在 ES 6 及以上才上生效。

当我们将 TypeScript 的代码生成目标设定为ES5或ES3,迭代器就只允许在array类型上使用。在非数组值上使用for..of语句会得到一个错误。即便这些非数组值已经实现了Symbol.iterator属性,也是不可以的。

编译器会生成一个简单的for循环作为for..of循环,比如:

const numbers = [1, 2, 3];

for (let number of numbers) {

console.log(number);

}

生成的代码为:

var numbers = [1, 2, 3];

for (var _i = 0; _i < numbers.length; _i++) {

var number = numbers[_i];

console.log(number);

}

2. generator

function * 是用来创建  generator 函数的语法。(在 MDN 的文档中 generator 称为生成器。)

调用 generator 函数时会返回一个generator 对象。generator 对象遵循迭代器接口,即通常所见到的 next、return 和 throw 函数。

generator函数用于创建懒迭代器,例如下面的这个函数可以返回一个无限整数的列表:

function* infiniteList() {

let i = 0;

while(true) {

yield i++;

}

}

var iterator = infiniteList();

while (true) {

console.log(iterator.next()); // { value: xxxx, done: false }

}

当然,也可以设定某个条件终止它,而不只是永远循环下去。如下所示:

function* infiniteList(){

let i = 0;

while(i < 3)

yield i++;

}

let gen = infiniteList();

console.log(gen.next()); // { value: 0, done: false }

console.log(gen.next()); // { value: 1, done: false }

console.log(gen.next()); // { value: 2, done: false }

console.log(gen.next()); // { value: undefined, done: true }

可以说这个设定是generator中最令人兴奋的部分。它在实质上允许一个函数可以暂停执行,比如当我们执行了第一次的 gen.next() 后,可以先去做别的事,再回来继续执行 gen.next(),这样剩余函数的控制权就交给了调用者。

当你直接调用 generator 函数时,它并不会执行,它只会创建一个 generator 对象。

《TypeScript实战指南》—2.1.7 iterator和generator

在下面的例子中,我们可以看到一个更灵活的使用方式:

function* generator(){

console.log('Execution started');

yield 0;

console.log('Execution resumed');

yield 1;

console.log('Execution end');

}

执行它,则会看到如下输出结果:

constiterator = generator();

console.log(iterator.next());

// "Execution started"

// { value: 0, done: false }

console.log(iterator.next()); // { value: 1, done: false }

// "Execution resumed'"

// { value: 1, done: false }

console.log(iterator.next());

// "Execution end"

// { value: undefined, done: true }

console.log(iterator.next());

// { value: undefined, done: true }

从上面代码可以得知:

generator 对象只会在调用next时开始执行。

函数在执行到yield语句时会暂停并返回yield的值。

函数在next被调用时继续恢复执行。

所以实质上generator函数的执行与否是由外部的 generator 对象控制的。

不过除了 yield 传值到外部,我们也可以通过 next 传值到内部进行调用。下面的例子展示了iterator.next传值的方式:

function* generator() {

const who = yield;

console.log('hello '+ who); // bar!

}

const iterator = generator();

Console.log(iterator.next());

// {value: undefined, done: false}

console.log(iterator.next('TypeScript'));

// hello TypeScript

// {value: undefined, done: true}

以上便是 next 和 return 函数的内容,接下来我们来看一下 throw 函数如何处理迭代器内部报错。

下面是iterator.throw的例子:

function* generator() {

try {

yield 1;

}

catch(error) {

console.log(error.message);

}

}

const iterator = generator();

iterator.next()

// {value: 1, done: false}

iterator.throw(new Error('something incorrect'));

// something incorrect

// {value: undefined, done: true}

通过以上的案例我们可以得知,外部是可以对 generator 内部进行干涉的:

外部系统可以传递一个值到 generator 函数体中。

外部系统可以抛入一个异常到 generator 函数体中。

Generator TypeScript

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:GaussDB(DWS)查看后台活跃SQL和执行状态
下一篇:一带一路电子签名服务加速一带一路国家经济发展——沃通CA
相关文章