当前位置: 首页 > Web前端 > HTML5

ES6(十五)——迭代器

时间:2023-04-05 01:08:54 HTML5

目录ES6如何让不支持遍历的结构可遍历?取出所有作者姓名for-of需要Object.entries转换并指定iterable协议——查找对象Iterator协议上是否有Symbol.iterator属性——迭代方式是什么?返回无参函数next,next返回一个包含done和value属性的对象Generator和iterator结合用例ES6-ES10学习布局ES6如何让不支持遍历的结构可遍历?让authors={allAuthors:{fiction:['AgathaChristie','J.K.罗琳','博士。苏斯'],科幻小说:['尼尔斯蒂芬森','亚瑟克拉克','艾萨克阿西莫夫','罗伯特海因莱因'],幻想:['J。R.R.托尔金','J.K.Rowling','TerryPratchett']}}取出所有作者姓名ES5方法遍历allAuthors看for(let[k,v]ofObject.entries(authors.allAuthors)){console.log(k,v)}//fiction(3)["AgathaChristie","J.K.Rowling","Dr.Seuss"]//scienceFiction(4)["NealStephenson","ArthurClarke","IsaacAsimov","RobertHeinlein"]//奇幻(3)["J.R.R.Tolkien","J.K.Rowling","TerryPratchett"]//所以正确的写法是:letr=[]for(let[k,v]的Object.entries(authors.allAuthors)){r=r.concat(v)}console.log(r)//[“阿加莎·克里斯蒂”、“J.K.罗琳”、“苏斯博士”、“尼尔·斯蒂芬森”、“亚瑟·克拉克”、“艾萨克·阿西莫夫”、“RobertHeinlein","J.R.R.Tolkien","J.K.Rowling","TerryPratchett"]每次都需要遍历,需要转换obj不支持遍历的对象,还需要知道authors的内部结构.我们的目标是:优雅数据结构的内置逻辑不需要关心letr=[]for(letvofauthors){console.log(v)r.push(v)}所以ES6方式ofwriting//固定写法authors[Symbol.iterator]=function(){//输入this,对象本身letallAuthors=this.allAuthorsletkeys=Reflect.ownKeys(allAuthors)console.log(keys)//["fiction","scienceFiction","fantasy"]letvalues=[]//是key的值return{//必须返回一个方法next(){console.log(values)//在开始values.length为0,如果为0则进入循环过程取第一个元素,用完弹出}}//必须返回两个值return{done:!values.length,value:values.shift()}}}}letr=[]for(letvofauthors){r.push(v)}console.log(r)//[“阿加莎·克里斯蒂”、“J.K.罗琳”、“苏斯博士”、“尼尔·斯蒂芬森”、“亚瑟·克拉克”、“艾萨克·阿西莫夫”、“罗伯特·海因莱因”,“J.R.R.托尔金”,“J.K.Rowling","TerryPratchett"]for-of需要Object.entries进行转换letobj={1:"hello","a":"hi"};for(letiofobj){console.log(i,obj[i]);}//Error:UncaughtTypeError:objisnotiterableletobj1=Object.entries(对象);console.log(obj1)//[Array(2),Array(2)]for(let[k,v]ofobj1){console.log(k,v)}//1hello//ahi指定可迭代协议——找出对象上是否有Symbol.iterator属性可迭代协议允许JavaScript对象定义或定制它们的迭代行为,例如(定义)什么值可以在for...ofstructure(get)有些内置类型是内置的可迭代类型,具有默认的迭代行为,例如Array或Map,而有些类型则不是(例如Object)。为了成为可迭代对象,一个对象必须实现@@iterator方法,也就是说这个对象(或者它的原型链原型链上的一个对象)必须有一个名为Symbol.iterator的属性,这里引用遍历——for-of(ES6new)iteratorprotocol——什么样的迭代方式?返回无参函数next,next返回一个包含done和value属性的对象PS:这个结构是不是很像Generator?如果next函数返回一个非对象值(比如false和undefined),会显示TypeError(“iterator.next()returnedanon-objectvalue”)错误//Fixedwritingauthors[Symbol.iterator]=function(){//输入this,对象本身//输出返回值(格式要求)return{//必须返回一个next方法next(){//必须返回两个值return{done:false,//booleanfalse-遍历未结束true-遍历结束value:1//当前遍历项的值}}}}Generator和iterator结合使用理解Generator,参考文章ES6(14)-Generator//Iterableprotocolplus*isGeneratorauthors[Symbol.iterator]=function*(){//输入this,对象本身letallAuthors=this.allAuthorsletkeys=Reflect.ownKeys(allAuthors)console.log(keys)//["fiction","scienceFiction","fantasy"]letvalues=[]//是key的值//无限循环,如果退出,则自动停止退出while(1){if(!values.length){如果(keys.length){值=allAuthors[keys[0]]keys.shift()yieldvalues.shift()}else{//退出循环returnfalse}}else{yieldvalues.shift()}}}案例场景:你我共同开发atasklistapplicationiterator意义:外部无需关心内部结构,直接遍历即可获取所有数据//每个方法都是todos内部暴露的方法//最好直接把todos变成一个可迭代的对象consttodos={life:['eating','sleeping','玩豆豆'],learn:['Chinese','数学','外语'],work:['喝茶'],each:function(callback){constall=[].concat(this.life,this.learn,this.work)for(constitemofall){callback(item)}},[Symbol.iterator]:function(){constall=[...this.life,...this.learn,...this.work]让索引=0return{next:function(){return{value:all[index],done:index++>=all.length}}}}}todos.each(function(item){console.log(item)})//吃饭//睡觉//打豆豆//语文//数学//外语//喝茶for(constitemoftodos){console.log("for-of:"+item)}使用Generator函数实现迭代器方法改进上面的caseconsttodos={life:['eating','sleeping','打豆豆'],learn:['language','mathematics','foreignlanguage'],work:['drinktea'],each:function(callback){constall=[].concat(this.life,this.learn,this.work)for(constitemofall){callback(item)}},[符号。迭代r]:function*(){constall=[...this.life,...this.learn,...this.work]for(constitemofall){yielditem}}}for(constitemoftodos){console.log(item)}//吃饭//睡觉//打豆豆//语文//数学//外语//喝茶ES6-ES10学习布局