请选择 进入手机版 | 继续访问电脑版

好程序员-千锋教育旗下高端IT职业教育品牌

400-811-9990
我的账户
好程序员

专注高端IT职业培训

亲爱的猿猿,欢迎!

已有账号,请

如尚未注册?

[HTML5] 好程序员分享JavaScript迭代器的含义

[复制链接]
叶子老师 发表于 2019-7-19 16:20:01 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
  好程序员分享JavaScript迭代器的含义:什么是迭代器
  迭代器就是为实现对不同集合进行统一遍历操作的一种机制,只要给需要遍历的数据结构部署Iterator接口,通过调用该接口,或者使用消耗该接口的API实现遍历操作。
  迭代器模式
  在接触迭代器之前,一起先了解什么是迭代器模式,回想一下我们生活中的事例。我们在参观景区需要买门票的时候,售票员需要做的事情,他会对排队购票的每一个人依次进行售票,对普通成人,对学生,对儿童都依次售票。售票员需要按照一定的规则,一定顺序把参观人员一个不落的售完票,其实这个过程就是遍历,对应的就是计算机设计模式中的迭代器模式。迭代器模式,提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
  为什么要有迭代器
  回忆在我们的javascript中,可遍历的结构以及方式有很多。JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set,这样就有了四种数据集合,而遍历这四种结构都有不同的方法。举个栗子,服务端提供数据给前端,前端进行数据可视化工作,对数据进行遍历展示使用的for,但是由于业务的变化,使得后端返回的数据结构发生变化,返回对象或者是set,map,导致前端遍历代码大量重写。而迭代器的目的就是要标准化迭代操作。
  如何部署迭代器接口
  ES6为迭代器引入了一个隐式的标准化接口。Javascript许多内建的数据结构,例如Array、Map、Set、String、TypedArray、函数的 arguments 对象、NodeList 对象都具备 Iterator 接口。可以通过在控制台打印一个Array实例,查看其原型上具有一个Symbol.iterator属性(Symbol.iterator其实是Symbol('Symbol.iterator')的简写,属性名是Symbol类型代表着这个属性的唯一以及不可重写覆盖),它就是迭代器函数,执行这个函数,就会返回一个迭代器对象。
  虽然Javascript许多内建的数据结构已经实现了该接口,还有些结构是没有迭代器接口的(比如对象),那怎么办,我们需要写迭代器,那么就需要知道迭代器是如何工作的。下面代码实现的一个简单迭代器:
  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  //迭代器就是一个函数,也叫迭代器生成函数
  function Iterator(o){
  let curIndex = 0;
  let next = () => {
  return {
  value: o[curIndex],
  done: o.length == ++curIndex
  }
  }
  //返回迭代对象,该对象有next方法
  return {
  next
  }
  }
  let arr = [1,2]
  let oIt = Iterator(arr)
  oIt.next();//{value:1,done:false}
  oIt.next();//{value:2,done:false}
  oIt.next();// {value: undefined, done: true}
  oIt.next();// {value: undefined, done: true}
  调用迭代器函数,返回一个对象,该对象就是迭代器对象,对象上拥有next方法,每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
next()迭代
  在上面调用next方法的栗子中,需要注意的是:
  在获得数组最后一位元素的时候,迭代器不会报告done:true,这时候需要再次调用next(),越过数组结尾的值,才能得到完成信号done:true。
  通常情况下,在已经迭代完毕的迭代器对象上继续调用next方法会继续返回{value: undefined, done: true}而不会报错。
  可选的return()和throw()
  遍历器对象除了必须具有next方法,还可以具有可选的return方法和throw方法。
  return方法被定义为向迭代器发送一个信号,表明不会在消费者中再提取出任何值。
  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  Object.prototype[Symbol.iterator] = function () {
  let curIndex = 0;
  let next = () => {
  return {
  value: this[curIndex],
  done: this.length == curIndex++
  }
  }
  return {
  next,
  return() {
  console.log('执行return啦')
  return {}
  }
  }
  }
  let obj = {
  0: 'a',
  1: 'b',
  2: 'c'
  }
  //自动调用---遇到对迭代器消耗提前终止的条件
  for (let item of obj) {
  if (item == 'c') {
  break
  } else {
  console.log(item)
  }
  }
  //自动调用---抛出异常
  for (let item of obj) {
  if (item == 'c') {
  throw new Error('Errow')
  } else {
  console.log(item)
  }
  }
  //手动调用
  let ot = obj[Symbol.iterator]()
  console.log(ot.return())
  上面代码中,throw方法的执行可以在某种情况下自动被调用,也可以手动调用。throw方法主要向迭代器报告一个异常/错误,一般配合生成器使用。
  迭代器分类
  迭代器分为内部迭代器和外部迭代器。
·   内部迭代器:本身是函数,该函数内部定义好迭代规则,完全接受整个迭代过程,外部只需要一次调用。例如Array.prototype.forEach方法、jQuery.each都是内部迭代器。
·   外部迭代器:本身是函数,执行返回迭代对象,迭代下一个元素必须显式调用。使用forEach遍历,只可以一次性把数据全部拉取消耗,而迭代器可以用于以一次一步的方式控制行为,使得迭代过程更加灵活可控。
好程序员官网:http://www.goodprogrammer.org

精彩内容,一键分享给更多人!
回复

使用道具 举报

您需要登录后才可以回帖

本版积分规则

关注我们
好程序员
千锋好程序员

北京校区(总部):北京市海淀区宝盛北里西区28号中关村智诚科创大厦

深圳西部硅谷校区:深圳市宝安区宝安大道5010号深圳西部硅谷B座A区605-619

杭州龙驰智慧谷校区:浙江省杭州市下沙经济技术开发区元成路199号龙驰智慧谷B座7层

郑州校区:郑州市二七区航海中路60号海为科技园C区10层、12层

Copyright 2007-2019 北京千锋互联科技有限公司 .All Right

京ICP备12003911号-5 京公安网11010802011455号

请您保持通讯畅通1对1咨询马上开启