写点什么

JavaScript 高级程序设计(第 4 版)- 生成器

作者:掘金安东尼
  • 2022 年 7 月 31 日
  • 本文字数:1820 字

    阅读完需:约 6 分钟

JavaScript高级程序设计(第4版)-生成器

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


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


于是乎,借着更文契机,本瓜将开启一个小系列,带你重看一遍高级程序设计 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,返回 yiterator.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,以上便是本篇分享。 觉得不错点个赞吧👍👍👍,您的鼓励,我的动力,坚持原创质量好文~~ 欢迎评论留言 我是掘金安东尼,输出暴露输入,技术洞见生活。再会吧~~ 👋👋👋

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2022.07.14 加入

社会我瓜哥,人狠话不多😎 微信 anthony1453,加我交个朋友😎 正联合【机械工业出版社】出版《程序员成长手册》,敬请期待😎 真正的大师,永远怀着一颗学徒的心(易)😎

评论

发布
暂无评论
JavaScript高级程序设计(第4版)-生成器_JavaScript_掘金安东尼_InfoQ写作社区