举例说明iterator迭代器接口的使用方法,javascript generator

  举例说明iterator迭代器接口的使用方法,javascript generator

  本文已经给大家带来了一些关于JavaScript的知识,主要介绍JavaScript的前端迭代器和生成器。有需要的朋友可以参考一下,希望能有所帮助。

  【相关推荐:javascript视频教程,web前端】

  

Iterator 概念

  迭代器提供统一的接口机制,为各种不同的数据结构提供统一的访问机制。

  定义迭代器就是用next()方法提供一个对象。每次调用next()时,都会返回一个结果对象。结果对象有两个属性,value表示当前值,done表示遍历是否完成。

  函数makeIterator(数组){

  设索引=0;

  返回{

  下一个:function(){

  返回(

  数组.长度索引?

  {值:数组[索引]}:

  {完成:正确}

  )

  }

  }

  }

  let iterator=makeIterator([1 , 2])

  console . log(iterator . next());//{值: 1}

  console . log(iterator . next());//{值: 2}

  console . log(iterator . next());//{done: true}迭代器的作用:

  为各种数据结构提供统一简单的访问接口;以便数据结构的成员可以按一定的顺序排列;为.of消费

默认 Iterator 接口

   ES6提供了for of语句来遍历迭代器对象。让我们使用for of语句来遍历上面创建的迭代器:

  let iterator=makeIterator([1 , 2])

  for(让迭代器的值){

  console.log(值);

  } //迭代器不可迭代。结果报告了一个错误,指出迭代器不可迭代。这是为什么呢?ES6规定默认迭代器接口部署在数据结构的Symbol.iterator属性中。如果数据结构具有Symbol.iterator属性,则可以遍历该数据结构。

  我们将自定义makeIterator转换如下:

  const MakeIterator=(Array)=({

  [Symbol.iterator](){

  设索引=0;

  返回{

  下一个(){

  let length=Array.length

  if(索引长度){

  返回{value: Array[index ]}

  }否则{

  返回{done: true}

  }

  }

  }

  }

  })

  for(让MakeIterator的值([1,2]){

  console.log(值)

  }

  //1

  //2

Iterator 的 return()

  我们为MakeIterator添加返回方法。如果的.of循环提前退出(通常是因为错误或break语句),将调用return()方法来终止遍历。

  基于这个特性,如果一个对象在完成遍历之前需要清理或释放资源,我们可以部署return()方法,包括在文件读取失败时关闭文件。

  const MakeIterator=(Array)=({

  [Symbol.iterator](){

  设索引=0;

  返回{

  下一个(){

  let length=Array.length

  if(索引长度){

  返回{value: Array[index ]}

  }否则{

  返回{done: true}

  }

  },

  return()

  返回{done: true}

  }

  }

  }

  })

  for(让MakeIterator的值([1,2,3]){

  console.log(value) //1

  //模式1

  打破;

  //模式2

  //抛出新错误( Error );

  }

原生具备 Iterator 接口的数据结构

   array SetMap类数组对象,如arguments对象、DOM NodeList对象、typedArray对象//arguments对象。

  函数sum(){

  for(让参数值){

  console.log(值)

  }

  }

  sum(1,2)

  //1

  //2

  //typedArray对象

  设type arry=new int 8 array(2);

  type arry[0]=1;

  type arry[1]=2;

  for(让typeArry的值){

  console.log(值)

  }

  //1

  //2生成器对象函数* gen(){

  产量1;

  产量2;

  }

  for(let值为gen()){

  console.log(值)

  }StringQ:为什么Object没有原生迭代器?

  答:对象默认不部署迭代器接口的原因是不确定先遍历对象的哪个属性,后遍历哪个属性。

  本质上,遍历是一个线性过程。对于任何非线性数据结构,部署遍历接口相当于部署线性转换。

  但是严格来说,并不需要为对象部署遍历接口,因为对象实际上是作为一个Map结构使用的,ES5没有Map结构,但是ES6原生提供了。

  

调用 Iterator 接口的场合

  解构分配字母set=newset()。添加( a )。添加( b )。add( c );

  设[x,y]=set;//x= a ;Y=b 扩展运算符var str= hello

  [.str]//[h , e , l , l , o]扩展运算符是调用迭代器接口,所以Object不部署迭代器接口。为什么它也可以使用.接线员?

  原因:扩展运算符有两种。

  一个用于函数参数和数组扩展时,要求对象可迭代,另一个用于对象扩展,即{…obj} form,要求对象可枚举)让obj1={

  姓名:“钱逊”

  }

  设obj2={

  年龄:3岁

  }

  //数组对象是可枚举的

  让obj={.obj1,obj2}

  console . log(obj)//{姓名:钱逊,年龄:3}

  //默认情况下,普通对象是非迭代的

  让obj=[.obj1,obj2]

  console.log(obj) //对象不可迭代

模拟实现 for of

   of(obj,cb){

  let iterator value=obj[symbol . iterator]();

  let result=iteratorValue.next()

  而(!result.done){

  cb(结果值)

  result=iteratorValue.next()

  }

  }

  forOf([1,2,3],(值)={

  console.log(值)

  })

  //1

  //2

  //3

Generator

  

认识 Generator

  概念上,生成器函数是ES6提供的异步编程解决方案。生成器函数是一个状态机,它封装了多个内部状态。

  生成器函数也是一个遍历对象生成函数,执行后返回一个遍历对象。

  form 1.function关键字和函数名之间有一个星号;

  2.在函数体内使用yield表达式来定义不同的内部状态。

  函数* simpleGenerator(){

  产量1;

  产量2;

  }

  SimpleGenerator()如上所述,我们创建了一个简单的生成器,并用两个问题对其进行了探索:

  生成器函数运行后会发生什么?函数中yield表达式的作用是什么?函数* simpleGenerator(){

  console . log( hello world );

  产量1;

  产量2;

  }

  let generator=simple generator();//simple generator { lt;已暂停}}

  console.log(generator.next())

  //你好世界

  //{值:1,完成:假}

  console.log(generator.next())

  //{value: 2,done: false}生成器函数运行后返回一个生成器对象,而普通函数会直接执行函数内部的代码;每次调用generator对象的next方法,都会执行该函数,直到下一次yield关键字停止执行,并返回一个{value: Value,done: Boolean}对象。

  

next 方法的参数

   yield表达式本身没有返回值,或者总是返回undefined。下一个方法可以接受一个参数,该参数将作为前面yield表达式的返回值。通过next方法的参数,可以在生成器函数的不同阶段从外到内注入不同的值,从而调整函数行为。由于next方法的参数代表前一个yield表达式的返回值,所以第一次使用next方法时,传递的参数无效。

  函数sum(x){

  返回函数(y){

  返回x y;

  }

  }

  console.log(sum(1)(2))

  //用下一个参数重写。

  函数* sum(x){

  设y=产量x;

  while(true){

  y=产量x y;

  }

  }

  设gen=sum(2)

  console.log(gen.next()) //2

  console.log(gen.next(1)) //3

  console . log(gen . next(2))//4

yield 表达式

   yield表达式的作用:定义内部状态,暂停yield表达式的执行,与return语句不同。

  产量表达式表示函数暂停执行,下一次再从该位置继续向后执行,而返回语句不具备位置记忆的功能一个函数里,只能执行一个返回语句,但是可以执行多个产量表达式任何函数都可以使用返回语句,产量表达式只能用在发电机函数里面,用在其他地方都会报错产量表达式如果参与运算放在圆括号里面;用作函数参数或放在赋值表达式的右边,可以不加括号函数*gen () {

  console.log(hello yield)

  console.log(hello (yield))

  console.log(hello 产量1)

  console.log(hello (yield 1))

  foo(收益率1)

  常量参数=产量2

  }基于发电机生成器函数中可以支持多个产量,我们可以实现一个函数有多个返回值的场景:

  函数* gen(num1,num2){

  产出数字1数字2

  产量num 1-num 2;

  }

  设res=gen(2,1);

  控制台。log(RES . next())//{ value:3,done: false}

  控制台。log(RES . next())//{ value:1,done: false}

Generator 与 Iterator 之间的关系

  由于发电机函数就是遍历器生成函数,因此可以把发电机赋值给对象的符号迭代器属性,从而使得该对象具有迭代程序接口发电机。实现方式代码更加简洁。

  让obj={

  姓名:"钱逊",

  年龄:3岁,

  [Symbol.iterator]:函数(){

  让那个=这个;

  let keys=Object.keys(that)

  设索引=0;

  返回{

  下一个:函数(){

  返回索引键,长度?

  {value: that[keys[index ]],done: false}:

  {值:未定义,完成:真}

  }

  }

  }

  }

  对于(对象的字母值){

  console.log(值)

  }发电机:

  让obj={

  姓名:"钱逊",

  年龄:3岁,

  [Symbol.iterator]:函数*(1)

  let keys=Object.keys(this)

  对于(设I=0;I key . length I){

  产生这个[keys[I]];

  }

  }

  }

  对于(对象的字母值){

  console.log(值)

  }

Generator.prototype.return()

  函数* gen() {

  产量1;

  产量2;

  产量3;

  }

  var g=gen();

  g.next() //{ value: 1,done: false }

  //如果return()方法调用时,不提供参数,则返回值的价值属性为不明确的

  g.return(foo) //{ value: foo ,done: true }

  g.next() //{ value: undefined,done: true }如果发电机函数内部有尝试.最后代码块,且正在执行尝试代码块,那么return()方法会导致立刻进入最后代码块,执行完以后,整个函数才会结束。

  函数*数字(){

  产量1;

  尝试{

  产量2;

  产量3;

  }最后{

  产量4;

  产量5;

  }

  产量6;

  }

  var g=numbers();

  g.next() //{ value: 1,done: false }

  g.next() //{ value: 2,done: false }

  g.return(7) //{ value: 4,done: false }

  g.next() //{ value: 5,done: false }

  g.next() //{ value: 7,done: true }

yield* 表达式

  如果想在发电机函数内部,调用另一个发电机函数。我们需要在前者的函数体内部,自己手动完成遍历,如果函数调用多层嵌套会导致写法繁琐不易阅读,ES6提供了产量*表达式作为解决方法。

  委托给其他生成器

  函数* g1() {

  产量2;

  产量3;

  }

  函数* g2() {

  产量1;

  产量* G1();

  产量4;

  }

  常数迭代器=G2();

  控制台。log(迭代器。next());//{值:1,完成:假}

  控制台。log(迭代器。next());//{ value: 2,done: false }

  控制台。log(迭代器。next());//{值:3,完成:假}

  控制台。log(迭代器。next());//{ value: 4,done: false }

  控制台。log(迭代器。next());//{值:未定义,完成:真}委托给其他可迭代对象

  函数* gen(){

  收益率* [1,2,3]

  }

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

Generator 函数的 this

  生成器函数返回一个遍历器,ES6规定这个遍历器是发电机函数的实例,继承了发电机。原型对象上的方法,但无法获取这上的属性,因为这时这是全局对象,而不是实例对象。

  函数* gen(){

  this.a=1

  }

  gen.prototype.say=function(){

  console.log(hi )

  }

  让obj=gen()

  控制台。log(生成的对象实例)//true

  你好

  obj.next()

  控制台。日志(对象。a)//未定义如果想像构造函数一样访问实例属性,可以修改这绑定到发电机。原型上。

  函数* gen(){

  this.a=1

  }

  gen.prototype.say=function(){

  console.log(hi )

  }

  let obj=gen.call(gen.prototype)

  控制台。log(生成的对象实例)//true

  你好

  obj.next()

  console.log(obj.a) //1

Generator 实现一个状态机

  函数*状态机(state){

  让过渡;

  while(true){

  if(transition===INCREMENT){

  状态;

  } else if(transition=== DECREMENT ){

  状态-;

  }

  转变=屈服状态;

  }

  }

  常数迭代器=状态机(0);

  控制台。log(迭代器。next());//0

  控制台。log(迭代器。next( INCREMENT ));//1

  控制台。log(迭代器。下一个(减量);//0【相关推荐:javascript视频教程、网络前端】以上就是Java脚本语言前端迭代器迭代程序与生成器发电机讲解的详细内容,更多请关注我们其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: