Iterator遍历器的作用

JS语言中包含众多具有“集合”性质的数据结构——比如数组、对象、Set以及Map等,很多时候用户会将其进行组合使用,比如数组里边嵌套对象,或是数组里边嵌套Map等,由此数据结构变得复杂起来。数据结构复杂化所导致的一个问题便是对其访问的难度会随之提升。对于具有“集合”性质并且存在多种不同数据结构嵌套的复杂结构,对其结构的遍历访问往往要求对数据结构进行逐层拆解,从而获得目标数据,这是一个复杂的过程,且复杂程度会随着结构复杂度而成倍提升。
为了便于进行访问,开发者在设计数据结构的同时也会开发相应的访问接口,通过对接口函数的直接调用从而“简化”对数据结构的访问过程(尽管从外部看来是简单明了的)。
Iterator遍历器的作用正是提供这样一个工具,其可以辅助开发人员,针对某个特定的(即由开发人员自己设计的)、具有“集合”性质的数据结构,建立一个个性化的遍历方案(或访问接口)。

Iterator遍历器的核心:next()方法

next()方法是实现Iterator遍历器的关键。
(1)从外部看,Iterator遍历器的实例对象只要调用next()方法,便能实现对数据结构的遍历访问。
(2)从内部看,该方法控制着返回的数据以及遍历是否结束的标识。

例程如下:

 var temp = creatIterator(['a','b','c']);console.log(temp.next());console.log(temp.next());console.log(temp.next());console.log(temp.next());function creatIterator(arr) {//由于要进行全局访问,长期保存变量值,因此此处用var//而不用let,var所具有的变量提升特性在这里是必要的var nextIndex = 0;return {next:function() {return nextIndex < arr.length?//如果索引变量小于当前传入数组的长度,则将对应的有效数据传出,并将遍历的状态标识done置为false{value:arr[nextIndex++],done:false}://如果索引变量大于当前传入数组的长度,则传出无效undefined,并将遍历的状态标识done置为true{value:undefined,done:true};}};
}

上述例程定义了一个函数,该函数可返回一个对象,通过该对象下的next()方法可实现对数组元素的遍历访问。
**注意:**该next()方法之所以具有移动、遍历的功能特性,完全取决于该方法中所定义的索引变量nextIndex是var属性(如果定义为let型变量,就没有这种效果了)。var所具有的变量提升特性可使得该变量在全局下有效。累加的结果会被长期记录,而不限于函数creatIterator()的作用块。
接下来说明如何部署一个具有默认Iterator接口的对象。

类部署Iterator接口

为类对象部署Iterator接口通常会为其声明Symbol.iterator属性(ES6规定)。一个数据结构若具有Symbol.iterator属性,在程序执行过程中即认为该数据结构具有“可遍历”的性质。

Symbol关键字说明
此处对Symbol关键字进行说明,若您已经对此有所掌握,可以直接跳过此节。
Symbol可作为一个数据类型,该数据类型具有唯一性(类似于产品出厂时带有唯一的出厂编号)

let type = Symbol();
console.log(type);

执行结果:

此处调用Symbol()函数可返回一个Symbol类型的值(不是对象),该值的类型是唯一的,具体看下边:

    let type1 = Symbol();let type2 = Symbol();console.log(type1);console.log(type2);if(type1===type2){console.log(true);}else{console.log(false)}

执行结果:

由上例可见,即使调用Symbol()函数,创建Symbol值的过程完全相同,所产生的结果依然是不同的(类型不同)
可以通过向Symbol()函数传递参数以为该Symbol类型添加描述(类似于代码注释或是附加说明),但对值类型的唯一性没有任何影响。

    let type1 = Symbol('saber');let type2 = Symbol('saber');console.log(type1);console.log(type2);if(type1===type2){console.log(true);}else{console.log(false)}

执行结果:

Symbol值使用场景的一个重要特点在于,该场景下并不关心目标的具体值是多少,只要目标是唯一的,可以与其它目标彼此区分的就可以。对Symbol值一种常见的使用方法是,将其作为对象的属性名,由于其具有的唯一性以防止对象的属性被轻易改写或覆盖。写法如下:

    let type = Symbol();//第一种写法let obj1 = {};obj1[type] = 'Hello';//第二种写法let obj2 = {[type]:'world'}console.log(obj1[type]);console.log(obj2[type]);

执行结果如下:

上述例子中,创建了两个对象obj1和obj2,并且分别为两个对象各添加了一个Symbol类型的属性,属性值分别为‘hello’和‘world’。
具有Symbol性质的对象属性在这里的写法可能会让一些人感到怪异,因为此处使用“[Symbol值]”直接作为属性名,而不是常规的用户自定义属性标识,这个习惯就好,因为接下来还会用“[Symbol值]”直接作为类对象的方法名(淦!!!)

为类对象部署Iterator遍历器接口
相比于数组、Set以及Map等线性数据结构(这些结构内部构成都是默认有序的)而言,用户自定义对象往往是非线性的(内部数据无严格的次序关系),因此对类对象部署遍历器的一个重要环节便在于——明确如何遍历这个对象。
为类对象部署Iterator遍历器接口的要点如下:
(1)该类对象必须包含Symbol.Iterator()方法,以声明该类对象是可以被遍历的;
(2)Symbol.Iterator()方法当中,必须返回一个包含next()方法的对象,以明确对类对象的遍历方式。包含Next()方法的对象和类对象自身可以是同一个,也可以不同。
示例代码如下:

class RangeIterator {constructor(start,stop) {this.value = start;this.stop = stop;}[Symbol.iterator] () {return this;}next() {var value = this.value;if(value < this.stop) {this.value ++ ;return {done:false,value:value};}return {done:true,value:undefined};}
}function range(start,stop) {return new RangeIterator(start,stop);
}for(var value of range(0,3)){console.log(value)}

上述代码定义了一个类RangeIterator,在该类中定义了名为next的方法,以指定对该类的遍历方式;其次包含了名为[Symbol.Iterator]的方法,在该方法中直接返回类自身(该类本身就包含next方法)由此满足要点2。
经过range()函数对该类进行实例化后,使用for…of语句进行遍历,执行结果如下:

此处注意一下,这里的value变量是var类型,所以其作用域是全局的,而不限于RangeIterator类的范围内。也正是如此,通过每次调用next()函数进行遍历的每一步才可被长期保存下来。

以上便是本人对Iterator遍历器使用的认知,如有不当之处,欢迎留言指正。

Iterator遍历器的使用相关推荐

  1. Iterator 遍历器的简单使用

    Object接口 实现Iterator 我们可以使用 ES6 的展开运算符 - 和 for-of- 去遍历带有 Iterator 接口的数据结构,需要注意的是,Object 本身不具备 Iterato ...

  2. 第十四节:ES6的 Iterator 遍历器到底是什么?

    对一个事物足够热爱,才会有这样的热情... 冲着这位同学的学习热情,前端君今晚就给大家再来一发. for...of为啥不遍历Object对象 第十三节我们讲了简单又实用的for...of,我们可以使用 ...

  3. Iterator遍历器和原生可遍历

    1. Iterator遍历器 ①Iterator是一个遍历器(迭代器),是一个统一的遍历方式.Iterator寻找是找不到,该方法在对象原型链上可以找到,Symbol.iterator():调用该方法 ...

  4. 【ES6】Set Map数据结构、Iterator遍历器

    Set() Set类似于数组,但是成员的值都是唯一的,没有重复的值.Set 本身是一个构造函数,用来生成 Set 数据结构. const s = new Set(); let arr = [2, 3, ...

  5. 设计模式之Iterator遍历器模式

    该设计模式是为了方便客户端将希望遍历的被放入容器.集合类的一组ADT对象,无需关心容器的具体类型. 也就是说,不管对象放在哪里,都提供同样的遍历方式.'' 更简单的说,无论是Set.Map.List, ...

  6. js的遍历器(Iterator)

    js的遍历器(Iterator)是什么 JavaScript 原有的表示"集合"的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set.这样就有 ...

  7. ES6之遍历器Iterator

    目录 一.什么是遍历器 二.如何部署遍历器 三.遍历器的应用 1. 解构赋值 2. 扩展运算符 3. Iterator与Generator函数 4. return和throw 总结 一.什么是遍历器 ...

  8. ES6 的遍历器接口 Iterator

    一.概念 遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员). Iterato ...

  9. iterator [ɪtə'reɪtə] 遍历器

    lterator 遍历器 遍历器是一种接口,它为不同的数据结构提供了统一的访问机制. 如果一个数据结构具有遍历器接口,那么就可以依次处理该数据结构的成员. 当前 javascript 用来表示集合的数 ...

最新文章

  1. 分享一个轻型ORM--Dapper选用理由
  2. Hadoop五个进程的作用和联系
  3. HTML+CSS+JS实现 ❤️圣诞抓礼物小游戏❤️
  4. Libevent源码分析-----连接监听器evconnlistener
  5. 战队不显示名字了_年仅17岁的新人选手!峡谷之巅1200分!被16家战队哄抢
  6. 高并发下如何缩短响应时间?
  7. mysql md 123456_MySQL修炼之路四
  8. Android项目实战(二):安卓应用程序退出的三种方法
  9. ThreadPoolExecutor运转机制详解
  10. 关于JSF Converter转换器的知识点
  11. 「破解」360快压不弹广告
  12. android动画送礼物,【Android】直播App礼物弹窗及连送礼物动画
  13. webmax函数高级教程整理集2
  14. 51单片机电路原理图_51单片机入门(第1篇):纯干货,单片机最小系统
  15. 安卓手机怎么root_手机怎么root
  16. 在java中定义标示符_JAVA中定义标识符时可以使用系统保留的关键字。
  17. 知识分享之Golang——在Golang中unicode码和中文的互相转换函数
  18. 润乾报表 echarts统计图分类显示不全
  19. 静态URL和动态URL有什么区别呢?
  20. Spring获取上下文的四种方式方式

热门文章

  1. 2022年压力管道巡检维护新版试题及压力管道巡检维护找解析
  2. 2013年10月16Aspx源码发布详情
  3. sigmoid neurons(激活函数)
  4. CSMA和ALOHA的python协议仿真分析(附带程序下载链接,面对对象实现)
  5. 脑机接口科普0006——为什么要搞脑机接口
  6. oracle中删除yuj_oracle中可以使用drop、delete和truncate三个命令来删除数据库中的表...
  7. 【天光学术】国际金融学论文:区块链背景下数字货币发展的机遇与问题(节选)
  8. 基于TLS协议的安全分析
  9. 安卓控件使用系列5:EditText输入表情图片
  10. 云应用开发之新浪SAE日志查看