Generator生成器 & Iterator迭代器

49 阅读3分钟

Iterator

  • 遍历器(Iterator)是一种机制(接口):为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作「for of循环」,依次处理该数据结构的所有成员

    • 拥有next方法用于依次遍历数据结构的成员
    • 每一次遍历返回的结果是一个对象 {done:false,value:xxx}
  • done:记录是否遍历完成

  • value:当前遍历的结果

  • 拥有Symbol.iterator属性的数据结构(值),被称为可被遍历的,可以基于for of循环处理

    • 数组
    • 部分类数组:arguments/NodeList/HTMLCollection...
    • String
    • Set
    • Map
    • generator object
    • ...
  • 对象默认不具备Symbol.iterator,属于不可被遍历的数据结构

class Iterator {

    constructor(assemble) {

        let self = this;

        self.assemble = assemble;

        self.index = 0;

    }

    next() {

        let self = this,

            assemble = self.assemble;

        if (self.index > assemble.length - 1) {

            return {

                done: true,

                value: undefined

            };

        }

        return {

            done: false,

            value: assemble[self.index++]

        };

    }

}

let itor = new Iterator([10, 20, 30, 40]);

console.log(itor.next()); //->{value:10,done:false}

console.log(itor.next()); //->{value:20,done:false}

console.log(itor.next()); //->{value:30,done:false}

console.log(itor.next()); //->{value:40,done:false}

console.log(itor.next()); //->{value:undefined,done:true}







// 让对象也具备迭代器规范

Object.prototype[Symbol.iterator] = function () {

    let assemble = this,

        keys = Object.keys(assemble)

            .concat(Object.getOwnPropertySymbols(assemble)),

        index = 0;

    return {

        next() {

            if (index > keys.length - 1) {

                return {

                    done: true,

                    value: undefined

                };

            }

            return {

                done: false,

                value: assemble[keys[index++]]

            };

        }

    };

};

let obj = {

    name: 'zhufeng',

    age: 12,

    teacher: 'team'

};

for (let value of obj) {

    console.log(value);

}







// 如果是类数组对象,可直接继承数组的Symbol.iterator「JQ也是如此」

let obj = {

    0: 10,

    1: 20,

    2: 30,

    length: 3

};

obj[Symbol.iterator] = Array.prototype[Symbol.iterator];

for (let value of obj) {

    console.log(value);

}

Generator

生成器对象是由一个generator function返回的,并且它符合可迭代协议和迭代器协议
developer.mozilla.org/zh-CN/docs/…

  • 普通函数 VS 生成器函数

  • 生成器函数 [[IsGenerator]]:true

  • 「把它当做一个实例 proto

  • 普通函数是 Function 的实例,普通函数.proto===Function.prototype

  • 生成器函数是 GeneratorFunction 的实例

  • 生成器函数.proto===GeneratorFunction.prototype

  • GeneratorFunction.prototype.proto===Function.prototype

  • ({}).toString.call(生成器函数) => "[object GeneratorFunction]"

  • 「把它作为一个构造函数 prototype」

  • 生成器函数不能被new执行 Uncaught TypeError: func is not a constructor

  • 当做普通函数执行,返回的结果就是生成器函数的一个实例

  • itor.proto -> func.prototype「空对象,没有constructor」 -> Generator.prototype「constructor:GeneratorFunction」{next/return/throw/Symbol(Symbol.toStringTag): "Generator"} -> 一个具备迭代器规范的对象「Symbol(Symbol.iterator)」 -> Object.prototype

// generator函数:function后面加一个*

function* fn() {

    console.log(this);

    return 10;

}

fn.prototype.query = function () {};

let gen = fn();

console.log(gen);

// gen.__proto__ -> fn.prototype「query」 -> GeneratorFunction.prototype「next/return/throw/Symbol.toStringTag」-> xxx.prototype「Symbol.iterator」 -> Object.prototype

console.log(typeof fn); //->"function"

console.log(fn instanceof Function); //->true 

function* generator() {

    console.log('A');

    yield 10;

    console.log('B');

    yield 20;

    console.log('C');

    yield 30;

    console.log('D');

    return 100;

}

let itor = generator();

console.log(itor.next()); //->{value:10,done:false}

console.log(itor.next()); //->{value:20,done:false}

console.log(itor.next()); //->{value:30,done:false}

console.log(itor.next()); //->{value:100,done:true}

console.log(itor.next()); //->{value:undefined,done:true} 

function* generator() {

    console.log('A');

    yield 10;

    console.log('B');

    yield 20;

    console.log('C');

    return 30;

}

let itor = generator();

console.log(itor.next()); //->{value:10,done:false}

console.log(itor.return('@return')); //->{value:"@return",done:true}

// console.log(itor.throw('@throw'));

console.log(itor.next()); //->{value:undefined,done:true}


// 每一次执行next的传递的值,是作为上一次yeild的返回值处理的

function* generator() {

    let x1 = yield 10;

    console.log(x1);

    let x2 = yield 20;

    console.log(x2);

    return 30;

}

let itor = generator();

itor.next('@1');

itor.next('@2');

itor.next('@3');


// yeild* 后面跟着一个新的itor,后期执行到这的时候,会进入到新的generator中执行

function* generator1() {

    yield 10;

    yield 20;

}

function* generator2() {

    yield 10;

    yield* generator1();

    yield 20;

}

let itor = generator2();

console.log(itor.next()); //value:10  done:false

console.log(itor.next()); //value:10 done:false

console.log(itor.next()); //value:20  done:false

console.log(itor.next()); //value:20 done:false

console.log(itor.next()); //value:undefined done:true