ES6 迭代器、生成器

一、迭代器

迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署iterator接口,就可以完成遍历操作。

1.什么迭代

  •            从一个数据集合中按照一定顺序,不断取出数据的过程我们就叫做迭代

 2.迭代和遍历有什么区别?

  •            遍历必须知道数据集合的长度,而迭代不需要
  •            迭代强调的是依次取出,不能够确定到底能取出来多少,也不确定能不能把数据取完

  3.迭代器需要满足的条件

  •             迭代器必须有得到下一个数据的能力
  •             判断是否有后续数据的能力

1.具备迭代器接口的数据,可以用for..of 遍历的数据:

  • Array
  • argument
  • Set
  • Map
  • String
  • TypedArray
  • nodeList

2.工作原理

  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
  • 接下来不断地调用next方法,指针一直往后移动,直到指向最后一个成员
  • 每调用next方法返回一个包含value和done属性的对象

3.可迭代对象上有这一个属性

        const arr = [1, 2, 3, 4, 5]
        console.log(arr);
        //创建一个指针对象,由Symbol.iterator创建
        let iterator = arr[Symbol.iterator]()
        console.log(iterator); //具有next方法
        //第一次调用next方法,指针自动指向数据结构的第一个成员
        console.log(iterator.next()); //{value:1,done:false};done表示是否迭代完成
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next()); //{value:undefined,done:true};完成

自己模拟一个迭代器

        const arr = [1, 2, 3, 4, 5]
        const iterator = {
            i: 0,
            next() {
                let result = {
                    value: arr[this.i],
                    done: this.i >= arr.length
                }
                this.i++;
                return result;
            }
        }
        let data = iterator.next()
        while (!data.done) {
            console.log(data.value)
            data = iterator.next()
        }
        console.log("迭代完成")

 4.自定义遍历数据

obj对象不是一个可迭代对象,不能用for..of遍历,因为没有Symbol.iterator,给obj写一个Symbol.iterator;

        // 自定义可迭代obj
        const obj = {
            a: 1,
            b: 2,
            [Symbol.iterator]() { //for of一定会走进这个函数
                const keys = Object.keys(this) //[a,b]
                let i = 0;
                return {
                    next: () => {
                        let propName = keys[i] //属性名
                        let propValue = this[propName]; //属性值
                        let result = {
                            value: {
                                propName,
                                propValue
                            },
                            done: i >= keys.length
                        }
                        i++;
                        return result;
                    }
                }
            }
        }
const iter = obj[Symbol.iterator]()
console.log(iter.next()); //{done: false,value: {propName: 'a', propValue: 1}
console.log(iter.next()); //{done: false,value: {propName: 'b', propValue: 2}
console.log(iter.next()); //{done: true,value: {propName: undefined, propValue:undefined}
 //可以用for..of遍历了
for (const iterator of obj) {
     console.log(iterator)
 }

二、生成器

生成器其实就是一个特殊的函数,

1.生成器的声明

调用生成器会产生一个生成器对象,具有next方法,调用这个方法会让生成器开始或恢复执行

next返回值类似迭代器

        function* fun() {
            console.log(1)
            console.log(2)
            console.log(3)
        }
        const iterator = fun()
        console.log(iterator) //一个迭代器对象,具有next方法
        iterator.next() //1 //2 //3

2.yield;函数代码的分割

生成器在遇到yield前正常执行,遇到后停止执行,再次调用next才能回复执行

        function* fun() {
            console.log(1)
            yield 'a';
            console.log(2)
            yield 'b';
            console.log(3)
        }
        const iterator = fun()
        console.log(iterator.next()) //执行第一段代码 打印1 next返回结果:{value: 'a', done: false}
        console.log(iterator.next()) //执行第二段代码 打印2 
        console.log(iterator.next()) //3   next返回{value: undefined, done: true}

遍历fun()

         function* fun() {
                console.log(1)
                yield 'a';
                console.log(2)
                yield 'b';
                console.log(3)
            }
        for (let v of fun()) {
            console.log(v); //执行代码打印1 //v=a //执行代码打印2 //v=b //3
        }

3.生成器函数的参数传递

调用生成的next方法时,可以传递参数,传递的参数会交给yield表达式作为返回值,第一次调用next方法时,传递的参数没有任何意义;

        function* fun(arg) {
            console.log(arg); //aaa
            var one = yield 1;
            console.log(one) //bbb
            var two = yield 2;
            console.log(two) //ccc
        }
        let iterator = fun('aaa')
        console.log(iterator.next()) //{value : 1 , done : false}
        console.log(iterator.next('bbb')) //{value : 2 , done : false}
        console.log(iterator.next('ccc')) //{value : undefined , done : true}

4.API

  • return()提前结束整个生成器函数,迭代过程也提前结束
  • throw()可以在生成器内部跑出一个错误,抛出到对应的行
       function* fun() {
            console.log(1)
            yield "a";
            console.log(2)
            yield 'b';
            console.log(3)
            yield 'c';
            console.log(4)
        }
        let a = fun()
        console.log(a.next()) //{value: 'a', done: false}
        console.log(a.return()) //结束 {value: undefined, done: true}
        console.log(a.next()) //{value: undefined, done: true}
        a.throw(new Error("aaaa"))

5.在生成器内部用别的生成器

        function* fun1() {
            yield 'a';
            yield 'b';
        }

        function* fun2() {
            yield* fun1()
            yield '1';
            yield '2';
            yield '3';
        }
        const a = fun2()
        console.log(a.next());//{value: 'a', done: false}
        console.log(a.next());//{value: 'b', done: false}
        console.log(a.next());//{value: '1', done: false}
        console.log(a.next());//{value: '2', done: false}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值