• ES6迭代器详细介绍


    目录

    1、迭代器是什么

    2、迭代器实现遍历的原理

    3、如何让对象实现for-of遍历

    4、内置迭代器——keys()、values()、entries() 


    1、迭代器是什么

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

    Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。

    Iterator接口就是对象里面的一个属性,这个属性叫做Symbol.iterator。而原生具备 Iterator 接口的数据结构有Array、Map、Set、String、TypedArray、arguments、NodeList ,它们都可以使用for-of来遍历。

    举个🌰:

    我们使用for-of来遍历一下数组:

    1. let arr = [23, 90, 45, 12, 'hello']
    2. for (let i of arr) {
    3. console.log(i);
    4. }

    返回结果如下:

    数组可以使用for-of实现遍历,是因为数组对象里面有一个Symbol.iterator属性。我们可以打印看一下:

     

    当我们使用for-of来遍历对象时:

    1. let obj = {
    2. name: 'zhangsan',
    3. age: 19
    4. }
    5. for (let i of obj) {
    6. console.log(i);
    7. }

     结果报错了:obj不可迭代

     这是因为对象没有Iterator 接口,即对象原型上没有Symbol.iterator属性,所以无法使用for-of来遍历对象。

    2、迭代器实现遍历的原理

    (1)创建一个指针对象(由Symbol.iterator来创建),指向当前数据结构的起始位置

    (2)第一次调用对象的next方法,指针自动指向数据结构的第一个成员

    (3)接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员

    (4)每次调用next方法都会返回一个包含value和done属性的对象(value 表示当前的值,done 表示遍历是否结束,true表示结束了,false表示还没有结束)

    这实际上也是for-of实现遍历的原理。

    1. let arr = [23, 90, 45, 12, 'hello']
    2. for (let i of arr) {
    3. console.log(i);
    4. }

    上面的数组能够实现遍历的原理如下:

    1. let arr = [23, 90, 45, 12, 'hello']
    2. // for (let i of arr) {
    3. // console.log(i);
    4. // }
    5. // 1.使用Symbol.iterator创建一个迭代器对象
    6. let iterator = arr[Symbol.iterator]()
    7. // 2.调用迭代器对象的next方法,每次调用next方法,指针都会往后移动,直到指向最后一个成员
    8. //每次调用next方法都会返回一个包含value和done属性的对象
    9. console.log(iterator.next()); //{ value: 23, done: false }
    10. console.log(iterator.next()); //{ value: 90, done: false }
    11. console.log(iterator.next()); //{ value: 45, done: false }
    12. console.log(iterator.next()); //{ value: 12, done: false }
    13. console.log(iterator.next()); //{ value: "hello", done: false }
    14. console.log(iterator.next()); //{ value: undefined, done: true }
    15. console.log(iterator.next()); //{ value: undefined, done: true }

    for-of 实现原理就是调用迭代器的next()方法,第一次调用将指针指向数据结构的第一个成员,依次调用依次指向,直到没有成员可以指向,done为true。

    3、如何让对象实现for-of遍历

    要想让对象也能够使用for-of来遍历,那么我们就需要给对象添加一个Iterator 接口,也就是在对象的原型上手动添加一个Symbol.iterator属性。

    简单实现思路如下:

    1、给对象添加一个iterator接口,即Symbol.iterator属性

    2、Symbol.iterator创建一个指针对象,因此我们返回一个对象

    3、指针对象里面有一个next方法

    4、每次调用next方法返回一个包含value和done属性的对象

    1. let obj = {
    2. name: "zhangsan",
    3. age: 19,
    4. gender: 'male',
    5. // 1.给对象添加一个iterator接口,即Symbol.iterator属性
    6. [Symbol.iterator]() {
    7. // 2.Symbol.iterator创建一个指针对象,因此我们返回一个对象
    8. return {
    9. // 3.指针对象里面有一个next方法
    10. next: function () {
    11. // 4.每次调用next方法返回一个包含value和done属性的对象
    12. return {
    13. value: '123',
    14. done: false
    15. }
    16. }
    17. }
    18. }
    19. }
    20. for (let i of obj) {
    21. console.log(i);
    22. }

    5、控制指针往后移动,并添加结束条件

    1. let obj = {
    2. name: "zhangsan",
    3. age: 19,
    4. gender: 'male',
    5. // 1.给对象添加一个iterator接口,即Symbol.iterator属性
    6. [Symbol.iterator]() {
    7. // 设置索引变量
    8. let index = 0
    9. // 2.Symbol.iterator创建一个指针对象,因此我们返回一个对象
    10. return {
    11. // 3.指针对象里面有一个next方法
    12. //这里需要使用箭头函数,否则this指向的就不是obj当前对象了
    13. next: () => {
    14. // 4.每次调用next方法返回一个包含value和done属性的对象
    15. if (index < Object.values(this).length) {
    16. // Object.values()方法返回对象的属性值构成的数组
    17. let result = {value: Object.values(this)[index], done: false}
    18. // 下标自增,让指针往后移动
    19. index++
    20. return result
    21. } else {
    22. //遍历结束
    23. return {value: undefined, done: true}
    24. }
    25. }
    26. }
    27. }
    28. }
    29. for (let i of obj) {
    30. console.log(i);
    31. }

    运行结果如下:

    4、内置迭代器——keys()、values()、entries() 

    为了更好地访问对象的内容,ES6为数组、Set、Map集合内置了三个API:keys()、values()、和entries() ,它们都返回一个迭代器对象,因为它们都返回一个迭代器对象,因此我们可以使用它们的返回值去调用next()方法,从而实现遍历。其中:

    keys() 用来遍历所有的键名;

    values() 用来遍历所有的键值;

    entries() 用来遍历[键名, 键值]组成的数组。(对于数组,键名就是索引值)

    我们以数组为例,使用一下这些方法来实现遍历:

    1. let arr = ['zhangsan', 'lisi', 'hello']
    2. let keys = arr.keys();
    3. let values = arr.values();
    4. let entries = arr.entries();
    5. console.log(keys.next()); //{ value: 0, done: false }
    6. console.log(keys.next()); //{ value: 1, done: false }
    7. console.log(keys.next()); //{ value: 2, done: false }
    8. console.log(keys.next()); //{ value: undefined, done: true }
    9. console.log(values.next()); //{ value: 'zhangsan', done: false }
    10. console.log(values.next()); //{ value: 'lisi', done: false }
    11. console.log(values.next()); //{ value: 'hello', done: false }
    12. console.log(values.next()); //{ value: undefined, done: true }
    13. console.log(entries.next()); //{ value: [ 0, 'zhangsan' ], done: false }
    14. console.log(entries.next()); //{ value: [ 1, 'lisi' ], done: false }
    15. console.log(entries.next()); //{ value: [ 2, 'hello' ], done: false }
    16. console.log(entries.next()); //{ value: undefined, done: true }
    17. for (let k of keys) {
    18. console.log(k);
    19. }
    20. /*
    21. 上面的for-of输出结果:
    22. 0
    23. 1
    24. 2
    25. */
    26. for (let k of values) {
    27. console.log(k);
    28. }
    29. /*
    30. 上面的for-of输出结果:
    31. zhangsan
    32. lisi
    33. hello
    34. */
    35. for (let k of entries) {
    36. console.log(k);
    37. }
    38. /*
    39. 上面的for-of输出结果:
    40. [ 0, 'zhangsan' ]
    41. [ 1, 'lisi' ]
    42. [ 2, 'hello' ]
    43. */
    44. // 手动调用next 遍历迭代器对象 {value:0 ,done:false}
    45. let result;
    46. while (!(result = values.next()).done) {
    47. console.log(result);
    48. }
    49. /*
    50. 上面的while循环输出结果:
    51. { value: 'zhangsan', done: false }
    52. { value: 'lisi', done: false }
    53. { value: 'hello', done: false }
    54. */


     

  • 相关阅读:
    微服务学习(九):安装OpenOffice
    金融数据分析(一)
    记录一次因执行时间过长锁已经释放导致finally块再次unlock引发的异常
    Spring Cloud学习(六)【统一网关 Gateway】
    Gee引擎常用功能简介
    【练习赛】2022年高教杯数学建模C题(第一题的第一小问)
    什么是架构基本概念和架构本质
    分库分表真实案例,扩容10倍容量
    【机械仿真】基于matlab GUI直齿圆柱齿轮应力计算【含Matlab源码 2077期】
    【模式识别】贝叶斯决策模型理论总结
  • 原文地址:https://blog.csdn.net/lq313131/article/details/126891697