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

你一定知道iterator和generator

时间:2023-03-28 15:15:33 HTML

generator是一种特殊的迭代器。生成器可以代替迭代器使代码更简洁。什么是迭代器?该对象需要符合迭代器协议。迭代器协议需要实现next方法。next方法有如下要求:0或1函数的输入参数和返回值必须包含两个属性,done和value。当遍历完成时,done为true,value为undefined。迭代器实现原理创建一个指向当前数据结构起始位置的指针对象。第一次调用对象的next方法,指针自动指向数据结构的第一个成员。接下来,不断调用next方法,指针向后移动,直到指向最后一个成员。每次调用next方法,返回一个包含value和done属性的对象。以下对象实现迭代器constnames=["kiki","alice","macus"];letindex=0;constnamesIterator={next:()=>{if(index==names.length){return{值:未定义,完成:真};}else{return{value:names[index++],done:false};}},};console.log(namesIterator.next())console.log(namesIterator.next())console.log(namesIterator.next())console.log(namesIterator.next())第四次调用next方法时,this当数据已经被迭代时,所以迭代器返回done为true。可迭代对象可迭代对象不同于迭代器对象。迭代器对象需要遵守迭代器协议(iteratorprotocol),并返回下一个方法。可迭代对象需要实现可迭代协议,即@@iterator方法,在代码中通过Symbol.iterator实现,这样在用for...of遍历数据时,会调用@@iterator方法.我们知道object这个数据类型是不能通过for...of遍历的,但是如果我们在上面实现@@iterator方法,它就变成了一个可迭代对象constobj={name:"alice",age:20,hobby:"唱歌",[Symbol.iterator]:function(){letindex=0;constkeys=Object.keys(this);return{next:()=>{if(index==Keys.Length){返回{value:undefined,do:true};}else{constkey=keys[index];索引++;返回{value:this[key],do:false}。,};for(letitemofobj){console.log(item);}constiterator=obj[Symbol.iterator]()console.log(iterator.next())console.log(iterator.next())console.log(iterator.next())console.log(iterator.next())可迭代对象的实现包括迭代器对象。原生可迭代对象简单来说就是可以通过for...of来遍历可迭代对象。原生可迭代对象包括:arrays,strings,arguments,set,mapconstarr=["kiki","alice","macus"];for(letitemofarr){console.log("array",item);}conststr="hello";for(letsofstr){console.log("string",s);}functionfoo(){for(letargofarguments){console.log("arguments",arg);}}foo(1,2,3,4);constmapEntries=[["name","alice"],["age","20"],];constmap=newMap(mapEntries);for(letmofmap){console.log("map",m);}constset=newSet(arr);for(letsofset){console.log("set",s);}以上是原生的可迭代对象可迭代对象的用途可迭代对象有以下几种使用for...of遍历扩展语法解构赋值创建其他类型的对象,如数组和setPromise.all也可以执行可迭代对象对象可以使用扩展语法和解构赋值,但它不是一个可迭代对象,而是一个单独的对象attributeconstiteratorObj={names:["kiki","alice","macus"],[Symbol.iterator]:function(){letindex=0;return{next:()=>{if(index==this.names.length){return{value:undefined,done:true};}else{return{值:this.names[index++],完成:f也};}}},};},};for(letitemofiteratorObj){console.log('for..of遍历可迭代对象:',item);}constnewArr=[...iteratorObj];console.log('扩展语法:',newArr);const[name1,name2,name3]=iteratorObj;console.log('解构赋值:',name1,name2,name3);constset=newSet(iteratorObj);constarr=Array.from(iteratorObj);console.log('set:',set);console.log('array:',arr)Promise.all(iteratorObj).then((value)=>{控制台。log("promise.all:",value);});以上方法都是在next方法中获取value值来迭代自定义类如果想让类成为可迭代对象,在类方法中添加Symbol.iterator方法并实现即可classStudent{constructor(name,age,爱好){this.name=name;这个。年龄=年龄;this.hobbies=爱好;}推(爱好){this.hobbies.push(爱好);}[Symbol.iterator](){让索引=0;return{next:()=>{if(index===this.hobbies.length){return{done:true,value:undefined}}else{turnn{returnvalue:this.hobbies[index++],done:错误的};}}},};}}conststudent=newStudent('kiki','16',['singing'])student.push('swimming')student.push('tennis')for(letitemofstudent){控制台。log(item)}这时候可以使用for..of方法遍历类中的hobbies属性。什么是生成器生成器称为生成器,可以用来控制函数什么时候执行和暂停生成器函数也是函数,但与普通函数有以下区别。生成器函数需要加一个*来执行,用一个变量来接收。每次使用next()方法执行一段代码,函数就会被yield关键字暂停,yield不仅可以传递参数,还可以返回值。返回值是一个生成器(generator),它是一种特殊的迭代器。上面的代码实现了生成器函数log(generator.next())console.log(generator.next())console.log(generator.next())调用next方法时,返回值与iterator一致,是一个包含value和完毕。这个时候的值是undefine,因为yield后面没有加上返回值。yield可以通过next方法传递参数和返回值。将参数传递给生成器函数,通过yieldfunction*foo(value1){console.log('开始执行')constresult1=yieldvalue1constresult2=yieldresult1constresult3=yieldresult2console.log('end执行')}constgenerator=foo('hello')console.log(generator.next('world'))console.log(generator.next('merry'))console.log(generator.next('christmas'))console.log(generator.next('done'))可以看到第一个next得到的值是通过生成器函数传递的,不是第一个next方法执行时的参数,所以这个值是其他方法的generatorfor"hello"insteadof"world"throw方法用于抛出异常(需要在生成器函数中捕获)return方法用于中断生成器函数的执行function*createGgenerator(){console.log("开始执行");试试{yield"hello";console.log("你好");}catch(error){yielderror;}产量“世界”;console.log("结束执行");}constgenerator=createGenerator();console.log(generator.next());console.log(generator.throw("throw"));console.log(generator.return(“返回”));使用return方法后done变为true,value变为return函数中传入的值。生成器取代了迭代器。生成器是一种特殊的迭代器。通过生成器,可以在某些场景下进行一些替换。让代码更简洁//迭代器实现了next方法functioncreateArrayIterator(arr){letindex=0;return{next:function(){if(index==arr.length){return{value:undefined,done:true};}else{return{value:arr[index++],done:false};}},};}//生成器遍历暂停函数function*createArrayGenerator(arr){for(letitemofarr){yielditem}}//yield语法糖function*createArraYield(arr){yield*arr}constarr=['alice','kiki','macus']constiterator=createArrayIterator(arr)console.log(iterator.next())console.log(iterator.next())console.log(ititerator.next())console.log(iterator.next())constgenerator=createArrayGenerator(arr)console.log(generator.next())console.log(generator.next())console.log(generator.next())console.log(generator.next())constyieldedGen=createArraYield(arr)console.log(yiledGen.next())console.log(yiledGen.next())console.log(yiledGen.next())console.log(yiledGen.next())上面三个方法实现的功能是一致的。生成器类中遍历的方法由迭代器改为生成器类Student{constructor(name,age,hobbies){this.name=name;这个。年龄=年龄;this.hobbies=爱好;}推(爱好){this.hobbies.push(爱好);}*[Symbol.iterator](){yield*this.hobbies}}conststudent=newStudent('kiki','16',['singing'])student.push('游泳')student.push('tennis')for(letitemofstudent){console.log(item)}以上就是iterator和generator的用法和联系。关于高级js,开发者需要掌握的东西还是很多的。可以看看我写的其他博文,正在更新中~