详解Iteritor迭代器&&Generator生成器

前言

es6新增内容: let /const /class es6Module模块规范(import export )Symbol /Biginit 箭头函数,解构赋值....数组和对象及正则的一些方法,模板字符串

promise proxy Iterator Generator

Iterator 迭代器

Iterator只是一种机制,可以为不同的数据结构提供统一的循环和迭代规范, 而for of循环本身就是基于这种机制进行迭代的

拥有Iterator机制的对象,必须具备一个next方法:执行这个方法可以依次访问对象中的每一个成员

执行next返回值是一个对象 value 当前迭代的这一项 done记录是否迭代完成

代码

<script>
    class Iterator {
        constructor(assemble) {
            let self = this;
            self.assemble = assemble;
            self.index = 0;
        }
        next() {
            let self = this,
                assemble = self.assemble;
            if (self.index > assemble.length - 1) {
                return {
                    value: undefined,
                    done: true
                }
            }
            return {
                value: assemble[self.index++],
                done: false
            }
        }
    };
    let itor = new Iterator([10, 20, 30, 40])
    console.log(itor.next());//-->(value:10 dome:false)
    console.log(itor.next());//-->(value:20 dome:false)
    console.log(itor.next());//-->(value:30 dome:false)
    console.log(itor.next());//-->(value:40 dome:false)
    console.log(itor.next());//-->(value:undefined dome:true)
</script>

虽然不具备Iterator这个内置类,但是对于某些数据结构,他提供了  Symbol.iterator属性方法,这个方法具备了迭代器规范,基于这个方法依次迭代数据中每一项

  • 数组 array.prototype.  Symbol.iterator=function
  • string.prototype
  • NodeList.prototype
  • set.prototype
  • map.prototype
  • arguments
  • Generator
  • object.prototype上不具备  Symbol.iterator,一个普通对象默认不能基于迭代器规范循环的,也就是不能使用 for ..of..循环

把[Symbol.iterator]方法执行,返回一个具备迭代器规范的itor对象,基于itor.next()依次执行,就可以获取到数据集合中的每一项

    let arr = [10, 20, 30]
    let itor = arr[Symbol.iterator]();
    console.log(itor.next());//{value: 10, done: false}
    console.log(itor.next());//{value: 10, done: false}
    console.log(itor.next());//{value: 10, done: false}
    console.log(itor.next());//{value: 10, done: false}

es6中新提供的for..of循环,就是按照这套机制迭代的

先去找arr.Symbol.iterator执行,(如果集合不具备这个属性就会报错),返回一个迭代器对象 itor

每一轮循环都会执行一次itor.next()方法,把结果中的value,赋值给循环中的value当done为true时则结束整个循环(不能得到索引)

  let arr = [10, 20, 30]
    for (let value of arr) {
        console.log(value);
    }

js中常用的循环

密集数组;[10,20,30] 稀疏数组:[1:20 2:30 length:6],

  • for循环, while循环,
  • array.prototype.forEach:迭代的时候,对于稀疏数组,只迭代有内容的
  • for of循环 ( 扩充:for await of)
  • for in循环

性能从高到底:for循环(基于let创建私有的i)-->for循环(基于var创建的全局i)&&while循环-->forEatch(内部封装的方法,肯定做了一些逻辑判断处理,所以稍微比命令式编程慢了一些)-->for/of循环-->for/in循环(他会依次查找私有和原型链上所以可枚举属性,所以比其他循环慢很多,项目中不建议使用for./in循环)

Generator

Generator生成器函数 function*(){}  fn(10,20) 返回一个迭代器对象,迭代器next()执行,控制代码执行

  • 函数体中的代码并没有执行,(实参值已经预先传递进去了)
  • 返回一个具备迭代器对象itor: next/return/throw
  • itor-->fn.prototype-->Generator.prototype(next/return/throw)-->原型对象  Symbol.iterator-->object.prototype

执行itor.next()才会执行函数中的代码

  • 把之前预先存储的实参赋值给形参变量
  • this-->window
  • 遇到 yeild或者return结束
  • 返回的结果是一个对象{value:yeild或者return后的值,done:false/true}

代码

   function* fn() {
            console.log('a');
            yield 10;
            console.log('b');
            yield 20;
            console.log('d');
            return 100;
        };
        let itor = fn();
        console.log(itor.next());//输出a {value:10,done:false}
        console.log(itor.next());//输出b {value:20,done:false}
        console.log(itor.next());//输出d {value:100,done:false}
        console.log(itor.next());//输出d {value:undefined,done:true}

next&&throw&&return

  •  throw:(itor.throw('异常原因'));//手动抛出异常,结束函数中的代码执行
  • return:(itor.return(100));// {value:100,done:true}遇到return则结束代码执行,done设置为true
  • next:执行下一步

代码

 function* fn() {
            yield 10;
            yield 20;
            return 30;
        };
        let itor = fn();
        console.log(itor.next());// {value:10,done:false}
        // console.log(itor.throw('异常原因'));//手动抛出异常,结束函数中的代码执行
        console.log(itor.return(100));// {value:100,done:true}遇到return则结束代码执行,done设置为true
        console.log(itor.next());//value: undefined, done: true}
}

next传参

第一次执行next传递的值没有用,每一次next传递的值,会作为上一次yield执行返回结果

   function* fn() {
            let res = yield 10;
            console.log(res);//200

            res = yield 20;
            console.log(res);//300

            res = yield 30;
            console.log(res);//400

        };
        let itor = fn();
        console.log(itor.next(100));// {value:10,done:false} 第一次执行next传递的值没有用
        console.log(itor.next(200))//把200赋值给第一个res {value:20,done:false} 每一次next传递的值,会作为上一次yield执行返回结果
        console.log(itor.next(300))//把200赋值给第二个res {value:30,done:false}
        console.log(itor.next(400))//把200赋值给第三个res {value:undefined,done:true}

yield*

   yield* fn1();//yeld*可以保证代码执行到这的时候,进入到新的Generator函数中

代码

      function* fn1() {
            yield 10;
            yield 20;
        }
        function* fn2() {
            yield 30;
            yield* fn1();//yeld*可以保证代码执行到这的时候,进入到新的Generator函数中
            yield 40;
        }
        let itor = fn2();
        console.log(itor.next());//{value: 30, done: false}
        console.log(itor.next());//{value: 10, done: false}
        console.log(itor.next());//{value: 20, done: false}
        console.log(itor.next());//{value: 40, done: false}
        console.log(itor.next());//{value: undefined, done: true}

 async原理

需求:串行发送三个请求

        const query = interval => {
            return new Promise(reslove => {
                setTimeout(() => {
                    reslove(interval)
                }, interval)
            })
        }

promise实现

 query(1000).then(value => {
            console.log('第一个成功', value);
            return query(2000)
        }).then(value => {
            console.log('第二个成功', value);
            return query(3000)
        }).then(value => {
            console.log('第三个成功', value);
        })

Generator实现

   function* generator() {
            let value = yield query(1000);
            console.log('第一个成功', value);

            value = yield query(2000);
            console.log('第二个成功', value);

            value = yield query(3000);
            console.log('第三个成功', value);
        };
        let itor = generator();
        // itor.next()//第一次请求的promose实例,接下来我们等待本次请求成功,获取到结果后,在执行下一次的next()    
        itor.next().value.then(val => {
            //val第一次请求的结果
            itor.next(val).value.then(val => (
                //val第二次请求的结果
                itor.next(val).value.then(val => {
                    //val第三次请求的结果
                    itor.next(val)
                })
            ))
        });

Async原理

   const isPromise = function isPromise(x) {
            if (x !== null && /^(object|function)$/i.test(typeof (x))) {
                var then;
                try {
                    then = x.then;
                } catch (_) {
                    return false;
                }
                if (typeof then === 'function') return true;
            }
            return false;
        }
        function AsyncFunction(generator, ...params) {
            return new Promise((reslove, reject) => {
                let itor = generator(...params);
                const next = val => {
                    let { value, done } = itor.next(val);
                    if (done) {
                        reslove(value);
                        return
                    }
                    if (!isPromise(value)) value = Promise.resolve(value);
                    value.then(val => next(val))
                        .catch(reasone => {
                            reject(reasone);
                            itor.throw(reasone);

                        })
                }
                next();

            })
        };

        AsyncFunction(function* generator() {
            let value = yield query(1000);
            console.log('第一个成功', value);

            value = yield query(2000);
            console.log('第二个成功', value);

            value = yield query(3000);
            console.log('第三个成功', value);
        }).then(value => {
            console.log("请求都成功", value);
        }).catch(reasone => {
            console.log('某一个请求失败了', reasone);
        })

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值