js中的迭代器与生成器(详解)

目录

一,迭代器

1.迭代器概念

2.迭代器的基本应用

3.迭代器原理

4.应用:自定义遍历数据

二,生成器

1.生成器概念

2.生成器的基本应用

3.yield表达式的值

4.应用:模拟获取数据

三,总结


一,迭代器

1.迭代器概念

迭代器(lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。

任何数据结构只要部署lterator接口,就可以完成遍历操作。

//以下数据结构支持lterator接口
String
Array
Map
Set
TypedArray
函数中的arguments对象
NodeList对象

2.迭代器的基本应用

for/of循环,扩展操作符 可以直接操作可迭代对象 

const xiyou = ['迭代器','生成器'];
for (let v of xiyou) {
    console.log(v)    // 迭代器,生成器
}
//注意:
// for/of v值保存的是键值
// for/in v值保存的是键名


data = [1, 2, 3, 4, 5, 6, 7, 8];
console.log(Math.max(...data));    // 8

迭代器也可用于结构赋值

let arr = [ 10 , 18 , 20];
let [a , b , c] = arr;
console.log(c);  // 20

3.迭代器原理

首先要了解3个不同的类型

  • 可迭代对象:类似于Array,Set,Map 都是可以迭代的。
  • 迭代器对象:是指任何具备next()方法的,且方法返回迭代结果对象的对象,用于执行迭代。
  • 迭代器结果对象:是指具有属性value和done的对象,用于保存每次迭代的结果。

要迭代一个可迭代对象,先调用迭代器方法获得一个迭代对象,然后重复调用迭代器对象的 next() 方法,直到返回迭代器结果对象 done 属性为 true;

可迭代对象的迭代器方法名为:[Symbol.iterator]

4.应用:自定义遍历数据

 自定义遍历数据,要想起迭代器

   const obj = {
            name: 'yiban',
            friend: [
                'duan',
                'zhou',
                'zhang',
                'wei'
            ],
            [Symbol.iterator]() {
                //索引变量
                let index = 0;
                 //创建一个指针对象
                return {
                    //创建next方法(必须)
                    next: () => {   //这里箭头函数解决this指向问题
                        if (index < this.friend.length) {
                            const res = {
                                value: this.friend[index],
                                done: false
                            };
                            index++;
                            return res
                        } else {
                            return {
                                value: undefined,
                                done: true
                            }
                        }
                    }
                }
            }
        }
        for (let v of obj) {
            console.log(v)
        }

二,生成器

1.生成器概念

生成器(Generators)是一种强大的新的ES6语法定义的迭代器,是一种异步编程解决方案。

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

2.生成器的基本应用

当调用生成器next()方法时,生成器函数会一直运行达到第一个yield表达式的时候,当第二次运行的时候会停在第二个yield上。

   //调用下面这个生成器函数不会运行下面的代码,而是会返回一个生成器对象
        //调用该对象的next()方法才会运行
        function* fn() {
            console.log('第一次执行');
            yield '分割线1';          //yield分割线调用一次只执行一次分割的位置
            console.log('第二次执行');
            yield '分割线2';
            console.log('第三次执行');
            yield '分割线3';
            console.log('第四次执行');

        }
        //调用生成器函数,得到一个生成器
        let han = fn();

        console.log(han.next());  //第一次执行  {value: '分割线1', done: false}
        console.log(han.next());  //第二次执行  {value: '分割线2', done: false}
        console.log(han.next());  //第三次执行  {value: '分割线3', done: false}
        console.log(han.next());  //第四次执行  {value: undefined, done: true}

3.yield表达式的值

生成器通过yield向调用者返回值,调用者通过next()方法给生成器传值。

在调用生成器的next()方法时,运行到第一个yield表达式,yield关键字后面的表达式会被求值,该值成为next()调用的返回值,这时生成器函数在求值yield表达式途中停,下一次调用next()方法时,传入的参数会变成暂停的yield表达式的值 。

 function* fn(str) {
                console.log(str); // 传参
                let a = yield 1;  //a == 'b'
                console.log(a);   // b
                let b = yield 2;  //b == 'c'
                console.log(b);   // c
                let c = yield 3;  //c == 'd'
                console.log(c);   // d
                return 100
            }
            //执行获取迭代器对象
        let han = fn('传参');
        //han.next()方法可以传入实参
        console.log(han.next('a'));  //第一次调用;参数将被丢弃,生成器回送1
        //执行传入的参数返回值为第一个yiele整体返回结果
        console.log(han.next('b')); //参数是b,生成器回送2
        console.log(han.next('c')); //参数是c,生成器回送3
        console.log(han.next('d')); //参数是d,生成器回送100

4.应用:模拟获取数据

模拟获取 用户数据 订单数据 商品数据
1秒后打印用户数据,1秒后打印订单数据,1秒后打印商品数据

        function fa() {
            setTimeout(() => {
                let yon = '用户数据';
                //传入参数并调用
                han.next(yon);
            }, 1000);
        }

        function fb() {
            setTimeout(() => {
                let din = '订单数据';
                han.next(din);
            }, 1000);
        }

        function fc() {
            setTimeout(() => {
                let shang = '商品数据';
                han.next(shang);
            }, 1000);
        }

        function* fn() {
            let a = yield fa();
            console.log(a);        //1s 用户数据
            let b = yield fb();
            console.log(b);        //2s 订单数据
            let c = yield fc();
            console.log(c);        //3s 商品数据
        }
        let han = fn();
        //调用
        han.next();

三,总结

生成器是一种强大的通用控制结构,可以使用生成器在单线程js代码中创建某种协作线程系统。尽管这些函数是异步的,但代码看起来还是顺序的同步的。

利用生成器来做异步操作会造成代码难以解释,ES6+新增了async/await 和 promise 提供了异步编程解决方案 。

猜你喜欢

转载自blog.csdn.net/m0_63831957/article/details/125815657