Iterator是一种接口,为各种不同的数据结构提供统一的访问机制。
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
一个数据结构只要具有 iterator 接口,就可以用for...of循环遍历它的成员。并不是所有的对象都能使用for...of循环,只有实现了Iterator接口的对象,才能够for...of来进行遍历取值。
作用1. 为各种数据结构,提供一个统一的、简便的访问接口;2. 使得数据结构的成员能够按某种次序排列;3. 创造一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。
Iterator的产生主要是为了使用for...of方法
Iterator其实就是一个具有 next()方法的对象,并且每次调用next()方法都会返回一个结果对象,这个结果对象有两个属性{ value: 表示当前的值,  done: 表示遍历是否结束
}
Iterator是一个特殊的对象:1. 它具有next()方法,调用该方法就会返回一个结果对象2. 结果对象有两个属性值:value和done。    3. value表示具体的返回值;done是布尔类型,表示集合是否完成遍历,没有则返回true,否则返回false4. 内部有一个指针,指向数据结构的起始位置。每调用一次next()方法,指针都会向后移动一个位置,直到指向最后一个位置

模拟Iterator

 function createIterator(items) {var i = 0;return {next: function () {var done = (i >= item.length);var value = !done ? items[i++] : undefined;return {done: done,value: value};},return(){ // 可选return方法console.log('提前退出');return {// 必须返回一个对象done:true}},// return: function () {//   return {//      done:true//   };// },};}// iterator 就是一个迭代器对象var iterator = createIterator([1, 2, 3]);console.log(iterator.next()); // { done: false, value: 1 }console.log(iterator.next()); // { done: false, value: 2 }console.log(iterator.next()); // { done: false, value: 3 }console.log(iterator.next()); // { done: true, value: undefined }console.log(iterator.next()); // { done: true, value: undefined }console.log(iterator.next()); // { done: true, value: undefined }var iterator = makeIterator([1, 2, 3]);// 不可以被for of 循环for (let value of iterator) {console.log(value); // Uncaught TypeError: iterator is not iterable}

可迭代对象Iterable

ES6还引入了一个新的Symbol对象,symbol值是唯一的。
一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口;
调用这个接口,就会返回一个遍历器对象。这样的数据结构才能被称为可迭代对象(Iterator),该对象可被for...of遍历var arr = [1, 2, 3];arr[Symbol.iterator] = function () {var _this = this;var i = 0;return {next: function () {var done = (i >= _this.length);var value = !done ? _this[i++] : undefined;return {done: done,value: value};}};}// 此时可以for...of遍历for (var item of arr) {console.log(item); // 1 2 3 }// for...of 遍历的其实是对象的 Symbol.iterator 属性
原生具备Iterator接口的数据结构在ES6中,所有的集合对象,包括数组,类数组对象(arguments对象、DOM NodeList 对象),MapSet字符串
都是可迭代的,都可以被for...of遍历,因为他们都有默认的迭代器。
数组var arr = [1, 2, 3];var iteratorObj = arr[Symbol.iterator]();console.log(iteratorObj.next());console.log(iteratorObj.next());console.log(iteratorObj.next());console.log(iteratorObj.next());
argumentsfunction test() {var obj = arguments[Symbol.iterator]();console.log(arguments);console.log(obj.next());console.log(obj.next());console.log(obj.next());}test(1, 2, 3);
NodeList<div class="test">1</div><div class="test">2</div><div class="test">3</div>const nodeList = document.getElementsByClassName('test')for (const node of nodeList) {console.log(node);}
mapconsole.log(Map.prototype.hasOwnProperty(Symbol.iterator)); // true

调用 Iterator 接口的场合

有一些场合会默认调用 Iterator 接口(即Symbol.iterator方法)
解构赋值let set = new Set().add('a').add('b').add('c’);let [x, y] = set;console.log(x, y); // a b
扩展运算符var str = 'hello';console.log([...str]); // ["h", "e", "l", "l", "o"]let arr = ['b', 'c'];console.log(['a', ...arr, 'd']); // ["a", "b", "c", "d"]
yield*// yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。let generator = function* () {yield 1;yield*[2, 3, 4];yield 5;};var iterator = generator();console.log(iterator.next()); // { value: 1, done: false }console.log(iterator.next()); // { value: 2, done: false }console.log(iterator.next()); // { value: 3, done: false }console.log(iterator.next()); // { value: 4, done: false }console.log(iterator.next()); // { value: 5, done: false }console.log(iterator.next()); // { value: undefined, done: true }function* entries(obj) {for (let key of Object.keys(obj)) {yield [key, obj[key]];}}for (let [key, value] of entries(obj)) {console.log(key, '->', value);}// a -> 1// b -> 2// c -> 3
其他// for...of、Set()、Map()、Array.from()等。我们主要是为了证明调用上面这些函数时着实是用到了Iterator接口。var arr = [1, 2, 3];arr[Symbol.iterator] = function () {var _this = this;var i = 0;return {next: function () {var done = (i >= _this.length);var value = !done ? _this[i++] : undefined;return {done: done,value: value + ' 手动添加的属性' // 添加自定义值};}};}// 输出结果显示手动修改生效,证明for...of调用了Iterator接口for (var item of arr) {console.log(item);// 1 手动添加的属性// 2 手动添加的属性// 3 手动添加的属性}var set = new Set(arr);console.log(set); // Set(3) {"1 手动添加的属性", "2 手动添加的属性", "3 手动添加的属性"}

计算生成的数据结构

有些数据结构是在现有数据结构的基础上,计算生成的。比如,ES6 的数组、Set、Map 都部署了以下三个方法,调用后都返回遍历器对象。1. entries() 返回一个遍历器对象,用来遍历[键名,键值]组成的数组。对于数组,键名就是索引值。2. keys() 返回一个遍历器对象,用来遍历所有的键名。3. values() 返回一个遍历器对象,用来遍历所有的键值。
 var arr = ["first", "second", "third"];for (let index of arr.keys()) {console.log(index);}// 0// 1// 2for (let color of arr.values()) {console.log(color);}// first// second// thirdfor (let item of arr.entries()) {console.log(item);}// [ 0, "first" ]// [ 1, "second" ]// [ 2, "third" ]

判断对象是否可迭代

  const isIterable = obj => obj != null && typeof obj[Symbol.iterator] === 'function';console.log(isIterable(new Set())); // true console.log(isIterable(new Map())); // true  console.log(isIterable([1, 2, 3])); // true console.log(isIterable("hello world")); // true

for…of循环不支持遍历普通对象

Iterator的产生主要是为了使用for...of方法。
而对象不像数组的值是有序的,遍历的时候根本不知道如何确定他们的先后顺序,所以要注意的是for...of循环不支持遍历对象。
如果非要遍历对象,同理对象也必须包含[Symbol.iterator]的属性并实现迭代器方法,可以通过手动利用Object.defineProperty方法添加该属性。
  var obj = {a: 2,b: 3}for (let i of obj) {console.log(i) // Uncaught TypeError: obj is not iterable}
类数组对象var obj = {0: 'one',1: 'two',length: 2};obj = Array.from(obj);for (var k of obj) {console.log(k)}
非类数组对象// 方法一var obj = {a: 1,b: 2,c: 3};obj[Symbol.iterator] = function () {var keys = Object.keys(this);var count = 0;return {next() {if (count < keys.length) {return {value: obj[keys[count++]],done: false};} else {return {value: undefined,done: true};}}}};for (var k of obj) {console.log(k);}// 方法二var obj = {a: 1,b: 2,c: 3};obj[Symbol.iterator] = function* () {var keys = Object.keys(obj);for (var k of keys) {yield [k, obj[k]]}};for (var [k, v] of obj) {console.log(k, v);}

Iterator(迭代器)相关推荐

  1. 2021年大数据常用语言Scala(十九):基础语法学习 iterator迭代器

    目录 iterator迭代器 使用迭代器遍历集合 iterator迭代器 scala针对每一类集合都提供了一个迭代器(iterator)用来迭代访问集合 使用迭代器遍历集合 使用iterator方法可 ...

  2. 设计模式(十五):Iterator迭代器模式 -- 行为型模式

    1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用 ...

  3. Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)

    1. Iterator迭代器 所有Collection的实现类都实现了iterator方法,该方法返回一个Iterator接口类型的对象,用于实现对集合元素迭代的便利.在java.util包下. 1) ...

  4. 使用Iterator迭代器循环集合

    1.Iterator迭代器用于遍历集合元素,获取迭代器可以使用. 2.Iterator提供了统一遍历集合元素的 方式 ,其提供了用于遍历集合的连个方法----- boolean  hasNext()判 ...

  5. vector容器与iterator迭代器

    vector容器 vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值.和string对象一样,标准库负责管理存储元素的相关内存.我们把vector称为容器,是因为它可以包含其他对象 ...

  6. Java基础23-集合类2(Set接口,Iterator迭代器)

    一.Set接口简介 根据API,Set接口是一个不包含重复元素的 collection.更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null ...

  7. Iterator迭代器

    Iterator迭代器 Iterator接口 java.util.Iterator接口:迭代器(对集合进行遍历)     有两个常用的方法         boolean hasNext() 如果仍有 ...

  8. 1.11 Lambda表达式遍历Iterator迭代器

    Java使用Lambda表达式遍历Iterator迭代器 Java 8 为 Iterator 引入了一个 forEachRemaining(Consumer action) 默认方法,该方法所需的 C ...

  9. Iterator迭代器原理

    引入 foreach (var item in hand) {遍历 item.Fly(); } 常见面试题:可以foreach的条件 对象具有迭代器对象(GetEnumerator方法) 或,对象实现 ...

  10. php 迭代器迭代中文时重复,3种方式解决iterator迭代器并发修改异常

    3种方式解决iterator迭代器并发修改异常ConcurrentModificationException 在使用迭代器的时候,时长会遇到 ConcurrentModificationExcepti ...

最新文章

  1. 超级智能城市:更高质量的幸福社会
  2. Mysql中设置默认时间为当前值
  3. git2.29.2.2怎么安装_MySQL5.5怎么安装
  4. 【Elasticsearch】ARS提升检索吞吐率
  5. netsh命令恢复网络_Linux TC模拟网络延迟、丢包、乱序
  6. Android ListView自定义分割线 header 和footer设置没有页眉和页脚
  7. HTML怎么写入形状,css3写各种形状(收集篇...)
  8. python一个类有几个实例对象_Python用一个类实例来解开一个对象
  9. 手机号码归属地全库生成
  10. Testbench基本入门
  11. robocode 安装 使用
  12. Sqlmap常用命令总结及注入实战(Access、mysql)
  13. three.js法线贴图与凹凸贴图的对比
  14. 清爽娱乐网源码 v5.69
  15. Ubuntu(护眼设置)安装屏幕色温调节软件F.lux
  16. 备赛笔记:Opencv学习:颜色识别
  17. 论 Erda 的安全之道
  18. Unity案例课程 - 涂鸦跳跳 Day 1
  19. 王兴的成功特质仅仅是爱思考吗?
  20. 计算机网络软考英语题,软考:网络工程师英文真题.doc

热门文章

  1. php 获取视频首帧,从视频中提取特定帧的最快方法(PHP/ffmpeg/anything)
  2. mysql导出选择两张表,Mysql导出(多张表)表结构及表数据 mysqldump用法
  3. stream对多个字段分组_java8 stream 如何按多字段分组,并对一个字段求和
  4. java基础经典面试题10道
  5. Flutter起步之安装
  6. PyCharm Python迁移项目
  7. Application Request Route实现IIS Server Farms集群负载详解
  8. OkHttp+Stetho+Chrome调试android网络部分(原创)
  9. android小细节
  10. 约瑟夫问题(顺序表)