es6 迭代器,生成器

今天我们来讲一下什么是迭代器和生成器。

迭代器

1.先来说一下什么是迭代?
将一种数据结构按照一定的顺序 不断取出的一个过程叫做迭代
迭代是将数据依次取出 不能保证把数据全部取出完 也不能确定取出多少

2.什么是迭代器
对迭代过程的封装,一般封装对象
迭代器拥有获取下一个数据的功能 在返回的数据中有数据状态,判断是否可以继续向下迭代

3.js中规定的迭代器
js中规定 一个对象中 含有next方法 并且这个next方法返回一个对象 那么我们就认为这个对象为迭代器

迭代器(对象)

var obj  = {
            next() {
                // 用于拿到后面的数据
              return { 
                //   就是返回的数据 
                  value : "666",
                //   判断是否还有下一个数据
                  done : false
              }  
            }
        }

接下来我们来写一个自定义的迭代器(数组)

        let arr = [1,2,3,4];
        // iterator(迭代器)
        const iterator = {
            // 声明一个变量让它从0开始迭代
            num : 0,
            next() {

               var result =  {
                    value : arr[this.num],
                    // 设置迭代状态 (后面还有没有数据)
                    done : this.num >= arr.length 
                }

                this.num++;
                return result;
            }
        }

        console.log(iterator);
        // 调用next一次取出对应的状态和值
        console.log(iterator.next());

每调用一次就会依次取出一个值,在这里大家可以发现return这是运用了闭包的原理

接下来我们来试着封装一下自定义数组的迭代器

function iterator(arr) {
            // 声明一个变量让它从0开始迭代
            let num = 0;
            return {
                next() {

                    var result = {
                        value: arr[num],
                        // 设置迭代状态 (后面还有没有数据)
                        done: num >= arr.length
                    }
                    num++;
                    return result;
                }
            }

        }

这就是底层的大概样子

接着我们来封装个经典的斐波拉契
斐波拉契,为1,1,2,3,5…
除了第一个和第二个为1以外,后面的为前两个之和

function createFeiboIter() {
            // 定义数组初始值
            let one = 1;
            let two = 1;

            // 记录当前位置
            let num = 1;
            return {
                next() {
                    let value;
                    if (num <= 2) {
                        value = 1;
                    } else {
                        value = one + two;
                    }
                    var res = {
                        value,
                        done: false // 因为斐波拉契没有极限所以返回一直未Flase
                    }
                    // 初始值重新赋予
                    one = two;
                    two = res.value;
                    num++;
                    return res;

                }
            }
        }

我们来看看数组的迭代器
// 在ES6里面 如果对象具有知名符号Symbol.iterator这个属性 那么就说明这个对象可以进行迭代

let iter = arr[Symbol.iterator]();

for of方法
数组可以直接用for of便利
普通和对象里面没有iterator接口 所以无法使用for-of进行遍历
类数组对象也可以进行遍历
对象设置迭代器

var obj = {
            a : 1, 
            b : 2,
            c : 3,
//让其可以使用for of方法
            [Symbol.iterator] () {
                // 拿到对象所有的键名
                const keys = Object.keys(this);
                let i = 0
                // 设置迭代器
                return {
                    next : () => {
                        const propName = keys[i];
                        const propValue = this[propName];

                         var result = {
                            value :  {
                                propName,
                                propValue
                            },
                            done : i++ >= keys.length

                        }
                        return result;
                    }
                }
            }
        }

生成器(generator)
什么是generator函数?
是一种ES6里面提供的一种方法 他是yield标识符和next方法调用 作用是可以是函数分段调用

怎么使用生成器?

function* love() {
            yield "111";
            yield "222";
            yield "333";
            return "没了"
        }
       var loves = love();
        console.log(loves.next());

function后面加*,下面执行语句用yield开头,如果有return则在执行完所有代码后,执行return里面的代码

调用next方法之后的逻辑 :
1.当函数调用next方法之后 在函数内部遇到了yield关键字 函数就会暂停执行 next方法的返回值就是yeild 后面接的数据
2. 当我们再次调用next方法时 就会从当前暂停的位置继续往下走 直到遇到下一个yield
3. 运行到最后 没有yield关键字 就会一直往后执行 直到遇到return 关键字 返回的是return后面的值 并且状态变成true
4. 最后没有遇到return 返回值为undefined 状态值为true
generator函数的特性 :
1. generator函数是分步执行的 以yield 为标志 表示函数暂停执行 通过调用next方法恢复函数执行
2. generator函数的写法跟普通函数有区别 在function关键字和函数名之前加一个* 通常情况下 *紧挨着function写
3. generator函数直接调用 是不会执行函数体的 而是要调用next方法 才能往下执行
4. generator函数调用之后 返回的值是一个iterator对象 只有调用next方法 才会迭代 进入下一个状态
生成器 : 生成器指的是 通过构造函数Generator创建出的生成器对象 让函数可以分布执行 生成器也是一个迭代器 同时也是一个可以迭代的对象
Async和 * 不能同时使用

下面我们来看看数组的生成器

 var arr = [1,2,3,4];
        function* createGenerator(arr) {
            for(const item of arr) {
                yield item;
            }
        }
        const iter = createGenerator(arr);
        console.log(iter.next());

下面我们在看看生成器里面调用另外一个生成器

function* f1() {
            yield 1;
            yield 2;
        }

        function* f2() {
            yield* f1(); // 在生成器内部调用其他的生成器  一定要在yield 后面加上*
            yield 4;
            // return 方法调用之后  就会提前结束生成器函数 整个迭代过程提前结束
            // return  9;
            // 可以在生成器内部抛出一个错误
            // throw 8;//报错
            yield 5;
            yield 6;
        }
        
        const gener = f2();
        console.log(gener.next());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值