JavaScript娓娓道来_Iterator迭代器

《JavaScript娓娓道来》系列文章属于JavaScript进阶知识,不同于《JavaScript面试大师》系列知识点+刷题的模式,该系列采取:实例+原理+代码的模式来展现写代码的思路,介绍JavaScript进阶过程中的难点,帮助初级工程师成长为中级和高级工程师。

实例:自定义一个数据结构myBook,该结构内部为(字符串-数组)键值对,表示我拥有的书本作者及对应的书名

let myBook = {
            AUTHOR_A: ['A1', 'A2', 'A3', 'A4', 'A5'],
            AUTHOR_B: ['B1', 'B2', 'B3', 'B4'],
            AUTHOR_C: ['C1', 'C2', 'C3', 'C4']
        }

现在需要获得我的所有书本,常用的方法是遍历它们,因此可以定义一个方法getBook,返回书名数组

let myBook = {
            AUTHOR_A: ['A1', 'A2', 'A3', 'A4', 'A5'],
            AUTHOR_B: ['B1', 'B2', 'B3', 'B4'],
            AUTHOR_C: ['C1', 'C2', 'C3', 'C4'],

            getBook: function () {
                let keys = Object.keys(myBook);
                let books = [];

                for (let i = 0, key = keys[i]; i < keys.length; i++) {
                    books = books.concat(myBook[key]);
                }

                return books;
            }
        }


myBook.getAuthorBook(); // ['A1', 'A2', 'A3', 'A4', 'A5','B1', 'B2', 'B3', 'B4','C1', 'C2', 'C3', 'C4']

但是定义方法有两个问题:

  1. 任意自定义的数据结构,都必须添加一个方法(getBook)遍历该结构,使用结构必须了解名称不同的方法
  2. 如果需要的数据结构是{ name:  ['AUTHOR_A', 'AUTHOR_B', 'AUTHOR_C' ],  book:  ['A1', 'A2',...,'C1',...,'C4'] }时,必须修改该方法

针对这两个问题,我们考虑:

  1. 任何数据结构的遍历方法采用同一方法名
  2. 遍历过程中返回统一的数据结构,开发者使用时可以按需包装该结构
let myBook = {
            AUTHOR_A: ['A1', 'A2', 'A3', 'A4', 'A5'],
            AUTHOR_B: ['B1', 'B2', 'B3', 'B4'],
            AUTHOR_C: ['C1', 'C2', 'C3', 'C4'],

            [uniqueMethod]: function () {
                // 迭代过程返回统一的数据结构

            }
        }

 

原理:ES6中引入了Iterator的概念,目的就是在于为各种数据结构,提供统一的访问接口。这里有两个概念,可迭代器对象Iterable和迭代器Iterator。使用Typescript表示他们的关系如下:

// 可迭代对象一定部署了[Symbol.iterator]方法
interface Iterable {
    [Symbol.iterator]() : Iterator;
}

// 执行 [Symbol.iterator]方法得到迭代器
interface Iterator {
    next() : IteratorResult;
}

// 迭代器具有next方法,返回迭代结果
interface IteratorResult {
    value: any;
    done: boolean;
}

概念放到示例中,我们希望myBook是可迭代对象Iterable,它有个唯一的方法能够返回每次的迭代器Iterator(即迭代结果) ,该方法名为 Symbol.iterator ,执行得到迭代器

 

代码:

部署 [Symbol.iterator] 方法之前,myBook是不可迭代的

let myBook = {
            AUTHOR_A: ['A1', 'A2', 'A3', 'A4', 'A5'],
            AUTHOR_B: ['B1', 'B2', 'B3', 'B4'],
            AUTHOR_C: ['C1', 'C2', 'C3', 'C4']
        }

for(let author of myBook){
    console.log(author);
}

 部署 [Symbol.iterator] 方法之后,myBook是可迭代的

let myBook = {
            AUTHOR_A: ['A1', 'A2', 'A3', 'A4', 'A5'],
            AUTHOR_B: ['B1', 'B2', 'B3', 'B4'],
            AUTHOR_C: ['C1', 'C2', 'C3', 'C4'],

            [Symbol.iterator]: function () {

                let index = 0;
                let keys = Object.keys(myBook);
                let author = keys[index];

                return {
                    next: function () {
                        return {
                            value: {
                                name: author,
                                book: myBook[author]
                                 },
                            done: keys[index++] ? false : true
                        }
                    }
                }
            }
        }

        for (let author of myBook) {
            console.log(author);
        }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值