ES6学习笔记(二)

152 阅读3分钟

1. 迭代器

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

(1)ES6创造了一种新的遍历语法,for...of,iterator主要供 for...of 消费。

(2)原生具备iterator接口的数据结构,Arguments、Array、List、Set、Map、String、TypedArray、NodeList

    const arr = ['tom','jerry','shuke','beita']
    for(let item of arr){
        console.log(item) // tom, jerry, shuke, beita
    }
    
    for(let key in arr){
        console.log(key) // 0,1,2,3
    }

(3)自定义迭代器

    const obj = {
        name:'obj',
        attriArray:['one','two','three','four'],
        // 想要一个对象能够拥有iterator迭代器,就必须让其具有Symbol.iterator属性
        [Symbol.iterator](){
            let index = 0
            let _this = this
            return {
                next:function{
                    if(index < _this.attriArray.length){
                        const result =  {
                            value:_this.attriArray[index],
                            done:false
                        }
                        index++
                        return result
                    }else{
                        const result = {
                            value:undefined,
                            done:true
                        }
                        return result
                    }
                    
                }
            }
        }
    }
    
    // 需求是,创建一个迭代器,当在迭代obj对象的时候,每次迭代输出结果是obj对象中attriArray数组的内容
    for(let item of obj){
        console.log(item) // one,two,three,four
    }

2. 生成器函数

生成器函数就是一个特殊的函数,用来做异步编程的新的解决方案。使用 * 进行标识,配合yield关键字进行使用

1. 示例

    // 在function关键字和函数名中间使用 * ,表示这个函数是一个生成器
    // yield 可以看做是函数代码的分隔符,把函数体分成不同的代码块,
    // 通过调用iterator.next()方法,来执行每一块的代码内容
    function * gen(){
        console.log('111')
        yield 'hello'
        console.log('222')
        yield 'world'
        console.log('333')
        yield '!!!'
        console.log('444')
    }
    
    let iterator = gen() // 生成器函数,返回一个迭代器对象
    console.log(iterator) // 直接打印 gen {suspended}
    
    iterator.next() // 111
    iterator.next() // 222
    iterator.next() // 333
    iterator.next() // 444
    
    // 打印iterator.next(),输出内容中的value就是yield后面表达式的执行结果
    console.log(iterator.next())// {value:'hello', done:false}
    console.log(iterator.next())// {value:'world', done:false}
    console.log(iterator.next())// {value:'!!!', done:false}
    console.log(iterator.next())// {value:undefined, done:true}
    
    // 既然返回的是一个迭代器对象,就可以使用for...of进行遍历
    for(let item of iterator){
        console.log(itme) 
    }
    // 打印结果
    // 111
    // hello
    // 222
    // world
    // 333
    // !!!
    

2. 生成器函数实例

实例1:1s 后输出111,再2s后输出222,再3s后输出333...

        // 如果用普通回调来实现,会出现回调地狱现象
        // setTimeout(() => {
        //     console.log(111);
        //     setTimeout(() => {
        //         console.log(222);
        //         setTimeout(() => {
        //             console.log(333)
        //             // 回调地狱...
        //         }, 3000);
        //     }, 2000);
        // }, 1000);


         // 使用生成器来实现需求
        function one() {
            setTimeout(() => {
                console.log(111);
                iterator.next();
            }, 1000);
        }

        function two() {
            setTimeout(() => {
                console.log(222);
                iterator.next();
            }, 2000);
        }

        function three() {
            setTimeout(() => {
                console.log(333);
                iterator.next();
            }, 3000);
        }

       
        function * gen(){
            yield one();
            yield two();
            yield three();
        }

        // 调用生成器函数
        let iterator = gen();
        iterator.next();

实例2:依次异步获取用户数据、订单数据、商品数据

        // 异步编程
        // 需求: 模拟获取数据流程 用户数据 > 订单数据 > 商品数据


        function getUsers() {
            setTimeout(() => {
                let userData = '用户数据'
                // 调用 next 方法,将用户数据传入,这里 next方法传入的参数,将作为函数体中第一个yield代码块的返回值
                iterator.next(userData);
            }, 1000);
        }

        function getOrders() {
            setTimeout(() => {
                let orderData = '订单数据'
                // 调用 next 方法,将订单数据传入,这里 next方法传入的参数,将作为函数体中第二个yield代码块的返回值
                iterator.next(orderData);
            }, 1000);
        }

        function getGoods() {
            setTimeout(() => {
                let goodData = '商品数据'
                // 调用 next 方法,将商品数据传入,这里 next方法传入的参数,将作为函数体中第三个yield代码块的返回值
                iterator.next(goodData);
            }, 1000);
        }

        // 声明生成器函数
        function * gen(){
           let users = yield getUsers();
           console.log(users);
           let orders = yield getOrders();
           console.log(orders);
           let goods = yield getGoods();
           console.log(goods);
        }

        // 调用生成器函数
        let iterator = gen();
        iterator.next();