JavaScript 高级程序设计第 4 版(后简称高程4),相较于第 3 版,增加了 ES6 至 ES10 的全新内容,删除了旧版过时的内容,并在原有基础上充实了更加翔实的内容。

中文译版于 2020 年发售,妥妥的“新鲜出炉”,你要是问本瓜:当今学 JavaScript 哪家强,我只能说:红宝书第 4 版最在行。

于是乎,借着更文契机,本瓜将开启一个小系列,带你重看一遍高级程序设计4(先前只是跳着跳着看),将抽取精华,用最简单的话解释核心点、尽量把握全局、快速过一遍的同时,记录与工友们分享~~

JS高级程序设计第 4 版:生成器的学习_迭代

正文

生成器,说白了,就是来自定义生成:迭代器对象的。

class Counter {
// Counter 的实例应该迭代 limit 次
constructor(limit) {
this.count = 1;
this.limit = limit;
}
next() {
if (this.count <= this.limit) {
return { done: false, value: this.count++ };
} else {
return { done: true, value: undefined };
}
}
[Symbol.iterator]() {
return this;
}
}

通过这种方式创建迭代器,太费劲儿了,并且这还只是简易版本,还不支持多次迭代,支持多次迭代的,还将用到闭包结构:

class Counter {
constructor(limit) {
this.limit = limit;
}
[Symbol.iterator]() {
let count = 1,
limit = this.limit;
return {
next() {
if (count <= limit) {
return { done: false, value: count++ };
} else {
return { done: true, value: undefined };
}
}
};
}
}

所以,生成器应运而生。

function* generatorFn() {
return 'foo';
}

const g = generatorFn();
console.log(g === g[Symbol.iterator]()); // true

可以看到:

​g === g[Symbol.iterator]()​​ 为 true,妥妥的,生成器就是来构造迭代器对象的最好证明!!

来看看生成器函数怎么写:

// 生成器函数
function* generator(i){
yield i + 1
var y = yield 'foo'
yield y
}

var iterator = generator(10) // 此时生成器函数不执行,返回一个迭代器

iterator.next() // {value: 11, done: false}
iterator.next() // {value 'foo', done: false}
iterator.next(10) // {value: 10, done: false},将 10 赋值给上一条 yield 'foo' 左侧的值,即 y = 10,返回 y
iterator.next() // {done: true}

生成器函数的语法规则是:

调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的 迭代器(iterator)对象。

当这个迭代器的 next() 方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置为止,yield 后紧跟迭代器要返回的值。

或者如果用的是 yield*(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。调用 next() 方法时,如果传入了参数,那么这个参数会作为上一条执行的 yield 语句的返回值。

其实,就把 yield 理解为一个缩小版的 return 即可;每执行一个 next,就 return 一个值,如果有赋值,则赋给上一个 return 结果里面去。

小结

高程第七章最后这一段小结,每一个字都值得认真去读:(建议背诵)


迭代器是一个可以由任意对象实现的接口,支持连续获取对象产出的每一个值。


任何实现 Iterable 接口的对象都有一个 Symbol.iterator 属性,这个属性引用默认迭代器。默认迭代器就像一个迭代器工厂,也就是一个函数,调用之后会产生一个实现 Iterator 接口的对象。

迭代器必须通过连续调用 next()方法才能连续取得值,这个方法返回一个 IteratorObject。这个对象包含一个 done 属性和一个 value 属性。前者是一个布尔值,表示是否还有更多值可以访问;后者包含迭代器返回的当前值。这个接口可以通过手动反复调用 next()方法来消费,也可以通过原生消费者,比如 for-of 循环来自动消费。


生成器是一种特殊的函数,调用之后会返回一个生成器对象。生成器对象实现了 Iterable 接口,因此可用在任何消费可迭代对象的地方。


生成器的独特之处在于支持 yield 关键字,这个关键字能够暂停执行生成器函数。使用 yield 关键字还可以通过 next()方法接收输入和产生输出。在加上星号之后,yield 关键字可以将跟在它后面的可迭代对象序列化为一连串值。


OK,以上便是本篇分享。 觉得不错点个赞吧👍👍👍,您的鼓励,我的动力,坚持原创质量好文~~ 欢迎评论留言 我是掘金安东尼,输出暴露输入,技术洞见生活。再会吧~~ 👋👋👋