欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES6(5):迭代器、生成器

程序员文章站 2022-07-13 08:42:12
...

一、迭代器

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

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

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

  • Array
  • Arguments
  • Set
  • Map
  • String
  • TypedArray
  • NodeList

3. 工作原理

  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
  • 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
  • 每调用 next 方法返回一个包含 value 和 done 属性的对象
  • 注: 需要自定义遍历数据的时候,要想到迭代器。

4. 示例:

//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];

//使用 for...of 遍历数组
for(let v of xiyou){
    console.log(v);
}

ES6(5):迭代器、生成器

//使用迭代器

let iterator = xiyou[Symbol.iterator]();

//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

ES6(5):迭代器、生成器

5. 自定义遍历数据 示例:

//声明一个对象
const banji = {
name: "终极一班",
stus: [
    'xiaoming',
    'xiaoning',
    'xiaotian',
    'knight'
],
[Symbol.iterator]() {
    //索引变量
    let index = 0;
    //保存this
    let _this = this;
    return {
        next: function () {
            if (index < _this.stus.length) {
                const result = { value: _this.stus[index], done: false };
                //下标自增
                index++;
                //返回结果
                return result;
            }else{
                return {value: undefined, done: true};
            }
        }
    };
}
}

//遍历这个对象 
for (let v of banji) {
console.log(v);
}

ES6(5):迭代器、生成器

二、生成器

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

1. 特殊在:

  • 字面量(函数声明 / 函数表达式)的关键字 function 后面多了一个 * ,* 前后允许有空白字符。 * 的位置没有限制
function * gen(){
    
}
function *gen(){
    
}
function* gen(){
    
}
  • 函数体中多了 yield 运算符,yield 相当于函数的暂停标记,也可以认为是函数的分隔符
function * gen(){   
    yield 'a';
    
    yield 'b';
    
    yield 'c';
    
}

2. 基本用法

function * gen(){
    console.log(111);
    yield 'a';
    console.log(222);
    yield 'b';
    console.log(333);
    yield 'c';
    console.log(444);
}

let iterator = gen();
iterator.next();
iterator.next();
iterator.next();
iterator.next();

ES6(5):迭代器、生成器

function * gen(){
    console.log(111);
    yield 'a';
    console.log(222);
    yield 'b';
    console.log(333);
    yield 'c';
    console.log(444);
}

let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

ES6(5):迭代器、生成器

  • 在调用 gen() 时,函数体中的逻辑并不会执行(控制台没有输出)
  • 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
    yield 语句后的值
  • 第一次调用 iterator.next(),函数开始执行,直到遇到第一个 yield 表达式为止
  • 第二次调用 iterator.next(),函数从上次 yield 表达式停下的地方,一直执行到下一个 yield 表达式以此类推,一直执行到函数结束 (如果有return语句,就执行到return 语句)
  • 第n次调用 iterator.next(),函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true

3. 生成器函数参数

function * gen(arg){
    console.log(arg);
    let one = yield 111;
    console.log(one);
    let two = yield 222;
    console.log(two);
    let three = yield 333;
    console.log(three);
}

//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));

ES6(5):迭代器、生成器
第二次调 iterator.next() 方法传入的实参,将作为第一个 yield 语句的返回结果。以此类推。

4. 生成器函数实例

实例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();

ES6(5):迭代器、生成器

实例2:模拟获取 用户数据 订单数据 商品数据
//模拟获取  用户数据  订单数据  商品数据 
function getUsers(){
    setTimeout(()=>{
        let data = '用户数据';
        //调用 next 方法, 并且将数据传入
        iterator.next(data);
    }, 1000);
}

function getOrders(){
    setTimeout(()=>{
        let data = '订单数据';
        iterator.next(data);
    }, 1000)
}

function getGoods(){
    setTimeout(()=>{
        let data = '商品数据';
        iterator.next(data);
    }, 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();

ES6(5):迭代器、生成器