ECMAScript——迭代器、生成器

86 篇文章 0 订阅
73 篇文章 0 订阅

ECMAScript

迭代器

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

1.ES6创造了一种新的遍历命令for…of遍历,iterator接口主要供for…of消费

2.原生具备iterator接口的数据(可用for of遍历)

​ 2.1 Array

​ 2.2 Arguments

​ 2.3 Set

​ 2.4 Map

​ 2.5 String

​ 2.6 TypedArray

​ 2.7 NodeList

工作原理:

​ 1.创建一个指针对象,指向当前数据结构的起始位置

​ 2.第一次调用对象的next方法,指针自动指向数据结构的第一个成员

​ 3.接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员

​ 4.每调用next方法返回一个包含value和done属性的对象

注意:需要自定义遍历数据的时候,要想到迭代器

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        const person = ['唐三藏', '孙悟空', '猪八戒', '沙悟净'];
        //使用for..in遍历数组
        // item保存的是键名
        /* for (let item in person) {
            //输出的是对应的下标
            // 0/1/2/3
            console.log(item);
        }
        //使用for..of遍历数组
        // item保存的是健值
        for (let item of person) {
            //输出的是内容
            // 唐三藏/孙悟空/猪八戒/沙悟净
            console.log(item);
        } */
        let obj = person[Symbol.iterator]();
        console.log(obj.next()); //{value: '唐三藏', done: false}
        console.log(obj.next()); //{value: '孙悟空', done: false}
        console.log(obj.next()); //{value: '猪八戒', done: false}
        console.log(obj.next()); //{value: '沙悟净', done: false}
        console.log(obj.next()); //{value: undefined, done: true}
    </script>
</body>

</html>

迭代器的应用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 声明一个对象
        const obj = {
            name: '大学生们',
            persons: [
                '张三',
                '李四',
                '王五',
                '周六'
            ],
            [Symbol.iterator]() {
                // 索引变量
                let index = 0;
                let _this = this;
                // 需要返回一个对象
                return {
                    // 对象里面要有一个next方法
                    next: function() {
                            // 在这里使用this,会有问题
                            if (index < _this.persons.length) {
                                const res = {
                                    value: _this.persons[index],
                                    done: false
                                };
                                // 索引自增
                                index++;
                                return res;
                            } else {
                                // 内容遍历完毕,返回undefined
                                return {
                                    value: undefined,
                                    done: true
                                };
                            }
                        }
                        // 箭头函数没有自己的this,它的this是这个函数创建时所在的所用域的this,
                        /*  next: () => {
                             if (index < this.persons.length) {
                                 const res = {
                                     value: this.persons[index],
                                     done: false
                                 };
                                 index++;
                                 return res;
                             } else {
                                 return {
                                     value: undefined,
                                     done: true
                                 };
                             }
                         } */
                }
            }
        };
        // 遍历对象
        for (let item of obj) {
            console.log(item); //Uncaught TypeError: obj is not iterable
        }
    </script>
</body>

</html>
生成器

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

作用:用来异步编程,

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 生成器函数
        function* func() {
            // console.log('hello,111');
            // yield后面跟一个表达式或者字面量
            // yield函数代码的分割符
            // 函数开始到第一个yield是一块,第一个yield到第二个yield是一块,
            // 第二个yield到第三个yield是一块,第三个yield到函数结束是一块
            yield '111';
            // console.log('hello,222');
            yield '222';
            // console.log('hello,333');
            yield '333'
            // console.log('hello,444');

        };
        // obj是一个生成器对象(可迭代)
        let obj = func();
        // console.log(obj);
        // 必须要调用next函数才能运行
        // 用next()来控制代码的向下执行
        // 调用一次next(),就会执行一段
        /*  obj.next(); //hello,111
         obj.next(); //hello,222
         obj.next(); //hello,333
         obj.next(); //hello,444 */
        //  遍历
        for (const item of func()) {
            // 遍历结果是yield后面的表达式
            console.log(item);
        }
    </script>
</body>

</html>

参数传递

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 生成器
        // 可以传入参数
        function* gen(arg) {
            // console.log('hello,1111');
            console.log(arg);
            yield 111;
            yield 222;
            yield 333;
        };
        // 生成器对象(可迭代)
        // 传入实参
        let obj = gen('AAA');
        /*  console.log(obj);
         // obj.next() //hello,1111
         // value是yield后面的表达式或者字面量;done为false,说明遍历还未结束
         console.log(obj.next()); //{value: 111, done: false}
         console.log(obj.next()); //{value: 222, done: false}
         console.log(obj.next()); //{value: 333, done: false}
         // done: true:表明遍历结束
         console.log(obj.next()); //{value: undefined, done: true} */
        //  第一次调用next方法,是执行gen函数的第一段代码(函数的开始到第一个yield)
        console.log(obj.next()); //AAA/{value: 111, done: false}
        // next方法可以传入实参,这个参数作为上一个yield语句的返回结果
        console.log(obj.next('BBB')); //{value: 222, done: false}
    </script>
</body>

</html>

生成器实例一

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 异步编程、文件操作、网络操作(ajax,request),数据操作
        // 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);
                timer.next();
            }, 1000)
        };

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

        function three() {
            setTimeout(() => {
                console.log(333);
                timer.next();
            }, 3000)
        };
        // 创建生成器函数
        function* gen() {
            // 先执行这个
            yield one();
            // 再执行这个
            yield two();
            // 最后执行这个
            yield three();
        };
        // 创建生成器对象
        const timer = gen();
        // 调用next()
        timer.next();
    </script>
</body>

</html>

生成器实例二

解决了回调地狱的问题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 模拟获取 用户数据    订单数据    商品数据
        // 要先得到用户数据,才得到订单数据,最才可以通过订单数据得到对应商品的数据要按照先后顺序
        function getUser() {
            setTimeout(() => {
                let data = '用户数据';
                // 调用next方法,并且将数据传入,这里运行第二段函数,参数作为上一次调用next方法的返回值
                obj.next(data)
            }, 1000)
        };

        function getOrders() {
            setTimeout(() => {
                let data = '订单数据';
                // 调用next函数,传入参数,作为上一次调用的返回值
                obj.next(data)
            }, 1000)
        };

        function getGoods() {
            setTimeout(() => {
                let data = '商品数据';
                // 调用next函数,传入参数,作为上一次调用的返回值
                obj.next(data)
            }, 1000)
        };
        // 创建生成器
        function* gen() {
            let user = yield getUser();
            // console.log(user); //用户数据
            let order = yield getOrders();
            // console.log(order);
            let goods = yield getGoods();
            // console.log(goods);
        };
        // 创建生成器对象
        const obj = gen();
        // 调用生成器函数,这里运行第一段函数
        obj.next(); //getUser()
    </script>
</body>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值