ES6 —— 学习之三

1. 迭代器

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

  • 1)ES6创造了一种新的遍历命令 for...of 循环 , Iterator 接口主要供 for...of 消费
  • 2)原生具备 iterator 接口的数据 (可用for...of 遍历)
    • Array
    • Arguments
    • Set
    • Map
    • String
    • TypedArray
    • NodeList
      一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是“可遍历的”(iterable)。
      ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”
let arr = [1,2,3,4,5,6];
for(let value of arr) {
    console.log(value);
}

// 输出 1,2,3,4,5,6
  • 3)迭代器工作原理

    • a) 创建一个指针对象,指向当前数据结构的起始位置

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

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

    • d) 每调用 next 方法返回一个包含 value 和 done 属性的对象

    <font color="red" size=2>注: 需要自定义遍历数据的时候,要想到迭代器。 </font>

let arr = [1,2,3];
let iterator = arr[Symbol.iterator]();
// done 为true表示数组已经遍历完了
console.log(iterator.next());   //{value: 1, done: false}
console.log(iterator.next());   //{value: 2, done: false}
console.log(iterator.next());   //{value: 3, done: false}
console.log(iterator.next());   //{value: undefined, done: true}
  • 4)迭代器应用 —— 自定义遍历

    <font color="red" size=2>没有 Symbol.iterator属性 , 不能使用迭代器</font>

let obj = {
    name: '天气',
    weather: [
        '晴天',
        '多云',
        '小雨',
        '大雨',
        '雾天'
    ]
}

// 需求使用 for...of 遍历obj,输出结果是weather里面的值
for(let value of obj) {
    console.log(value); //Uncaught TypeError: obj is not iterable
}

给 obj 对象添加 Symbol.iterator属性

let obj = {
    name: '天气',
    weather: [
        '晴天',
        '多云',
        '小雨',
        '大雨',
        '雾天'
    ],
    [Symbol.iterator]() {
        let index = 0; // 定义索引值
        let self = this; // 保存this指向
        return {
            next() {
                if (index < self.weather.length) {
                    const result = { value: self.weather[index], done: false };
                    index++;
                    return result;
                }
                return { value: undefined, done: true};
            }
        }
    }
}

// 需求使用 for...of 遍历obj,输出结果是weather里面的值
for(let value of obj) {
    console.log(value); // 晴天 多云 小雨 大雨 雾天
}

2. 生成器函数

执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

形式上,Generator 函数是一个普通函数,但是有两个特征。

* 一是,function关键字与函数名之间有一个星号
* 二是,函数体内部使用yield表达式,定义不同的内部状态
  • 1)声明与调用
    <font color="1ba784">生成器函数传入参数与普通函数无异</font>
function * gen(){
    yield 'hello';
    yield 'world';
    return 'ending';
}

let iterator = gen();
console.log(iterator.next());  //{value: "hello", done: false}
console.log(iterator.next());  //{value: "world", done: false}
console.log(iterator.next());  //{value: "ending", done: true}
console.log(iterator.next());  //{value: undefined, done: true}
  • 2)生成器函数实例
    <font color="1ba784">next方法可以传入参数,在生成器函数中获取,一个yield对应一个next传入的参数</font>
// 模拟获取     用户数据        订单数据        商品数据
function getUsers() {
    setTimeout(()=>{
        let data = '用户数据';
        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();
  • 3)生成器函数可以解决回调地狱,同时进行异步编程
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。