博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6的 Iterator 遍历器
阅读量:5795 次
发布时间:2019-06-18

本文共 3843 字,大约阅读时间需要 12 分钟。

for...of,我们可以使用它来遍历数组,字符串,Set和Map结构,但是有没有发现,我们并没有说它可以遍历Object对象,为什么不试试用它来遍历Object对象呢?

   我们试试看:

1   //定义一个的Object对象2     let obj = {"name":"前端君"};3 4     //咱们来for...of一下5     for(let v of obj){6         console.log(v);7     }8     //结果:报错9     //错误提示:obj[Symbol.iterator]不是一个function

 为什么数组,Set和Map结构又可以支持for...of的遍历呢?

   原来,要想能够被for...of正常遍历的,都需要实现一个遍历器Iterator。而数组,Set和Map结构,早就内置好了遍历器Iterator(又叫迭代器),它们的原型中都有一个Symbol.iterator方法;而Object对象并没有实现这个接口,使得它无法被for...of遍历。

 那么,我们就亲自来验证一下,它们的原型中到底是不是有个叫Symbol.iterator的方法:

2     //数组 3     Array.prototype[Symbol.iterator]; 4     //结果:function values(){...} 5  6     //字符串 7     String.prototype[Symbol.iterator]; 8     //结果:function [Symbol.iterator](){...} 9 10     //Set结构11     Set.prototype[Symbol.iterator];12     //结果:function values(){...}13 14     //Map结构15     Map.prototype[Symbol.iterator];16     //结果:function entries(){...}17 18     //Object对象19     Object.prototype[Symbol.iterator];20     //结果:undefined

  从上往下看,确实,唯独Object对象的原型上没有Symbol.iterator,返回了:undefined。其他的数据类型的原型上都含有一个名字叫Symbol.iterator的方法Function。

    注意:Symbol.iterator 是Symbol 对象的 iterator 属性,是一个特殊的Symbol值,因此,当它作为prototype对象属性名的时候,获取它的时候需要使用[ ]的形式: prototype[Symbol.iterator],不能使用点形式获取:prototype.Symbol.iterator。原因是点形式会把后面的值当作是字符串类型处理,而不是Symbol类型。

 也就说,只要一个数据结构拥有一个叫[Symbol.iterator]()方法的数据结构,就可以被for...of遍历,我们称之为:可遍历对象。比如:数组,字符串,Set和Map结构。

   现在你该知道为什么文章第一个案例会出现错误提示:obj[Symbol.iterator]不是一个function 了吧,因为Object对象的原型上压根就没有[Symbol.iterator]() 方法啊。还打算报警吗?

     既然我们知道拥有[Symbol.iterator]()方法就可以被遍历,我们就会好奇:[Symbol.iterator]方法到底做了什么这么牛逼,它的原理是什么? 

Iterator遍历器的原理

  当可遍历对象被for...of遍历的时候,[Symbol.iterator]()就会被调用,返回一个iterator对象。其中还有一个很重要的方法:next( ); 

1  //数组:一个可遍历对象 2     let arr = ['a','b','c']; 3     //调用数组的Symbol.iterator()方法 4     let iter = arr[Symbol.iterator](); 5  6   iter.next(); 7     //结果:{value: "a", done: false} 8  9     iter.next();10     //结果:{value: "b", done: false}11 12     iter.next();13     //结果:{value: "c", done: false}14 15     iter.next();16     //结果:{value: undefined, done: true}

   第1次调用next( )方法:返回数组的第1个元素:“a”,以及done的值为fasle,表示循环没有结束,继续遍历。

   第2次调用next( )方法:返回数组的第2个元素:“b”,以及done的值还是为fasle,表示循环没有结束,继续遍历。

   第3次调用next( )方法:返回数组的第3个元素:“c”,以及done的值依然为fasle,表示循环没有结束,继续遍历。

  第4次调用next( )方法:返回的value值为undefined,以及done的值变成了true,表示遍历结束。

   原来,for...of的原理就是:先调用可遍历对象的[Symbol.iterator]( )方法,得到一个iterator遍历器对象,然后就在遍历器上不断调用next( )方法,直到done的值为true的时候,就表示遍历完成结束了

自定义Iterator遍历器

   既然有了[Symbol.iterator]()方法就算是可遍历对象,那么我给Object对象手动加上一个[Symbol.iterator]()方法,那么它是不是可以被for...of遍历了?

 那我们就试试看,给一个Object对象加一个[Symbol.iterator]( )方法,看它是不是就能被for...of遍历了?

1 //定义一个的Object对象 2  3     let obj = { 4         0:"我是0", 5         1:"我是1", 6         2:"我是2", 7         length:3, 8         //添加[Symbol.iterator]方法 9         [Symbol.iterator] : function() {10             let _this = this;11             let index = 0;12             return {13                 next:() => {14                     let value = _this[index];15                     let done = (index >= _this.length);16                     index++;17                     return {value,done}18                 }19             }20         }21     };22 23     //咱们来for...of一下24     for(let v of obj){25         console.log(v);26     }27     //结果:"我是0"28     //      "我是1"29     //      "我是2"30

  上面这个案例也许你看了觉得很复杂,没看懂,没关系,我一起来分析它的结构就够了!

  我们定义了一个Object对象,同时给它添加了[Symbol.iterator]()方法,并在[Symbol.iterator]()方法实现了next( )方法,next( )方法返回的对象包含了value属性和done属性。

  具体细节如果不理解没关系,我们确实看到了给Object对象加上了[Symbol.iterator]()方法后,最后确实能被for...of遍历了。

   这就是说,我们可以创建一个可遍历的对象,并且自定义它的遍历行为。或者说可以通过添加[Symbol.iterator]()方法,把一个不可遍历的Object对象,变成可遍历的对象。

Iterator遍历器的价值 

   新特性for...of之所以能够遍历各种不同的数据结构,正是因为这个数据结构都实现了Iterator遍历器接口,供for...of遍历。如果没有实现Iterator接口,则该数据结构无法被for...of遍历,比如:普通的Object对象。

 本节小结

总结:Iterator遍历器为各种数据结构提供一个统一的遍历接口,使得for...of能够轻松简便地访问数据成员。 数据结构实现了Iterator接口,我们称之为可遍历对象。我们也可以自己创建可遍历对象并自定义遍历行为。

转载于:https://www.cnblogs.com/queenw/p/7283592.html

你可能感兴趣的文章
leetcode 116- Populating Next Right Pointers in Each Node
查看>>
spring项目启动错误——java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext...
查看>>
iOS开发网络篇—GET请求和POST请求
查看>>
字典dict
查看>>
游戏名词解释
查看>>
mongodb数据的导出和导入
查看>>
白话算法(7) 生成全排列的几种思路(二) 康托展开
查看>>
d3 v4实现饼状图,折线标注
查看>>
微软的云策略
查看>>
Valid Parentheses
查看>>
【ES6】数值的扩展
查看>>
性能测试之稳定性测试
查看>>
ES6的 Iterator 遍历器
查看>>
2019届高二(下)半期考试题(文科)
查看>>
【REDO】删除REDO LOG重做日志组后需要手工删除对应的日志文件(转)
查看>>
nginx 301跳转到带www域名方法rewrite(转)
查看>>
AIX 配置vncserver
查看>>
windows下Python 3.x图形图像处理库PIL的安装
查看>>
【IL】IL生成exe的方法
查看>>
network
查看>>