今天就把迭代器、生成器理个清楚!

441 阅读3分钟

第一次写文章,有错误请大佬斧正!

迭代器

  1.区分for of和for in

​  for of是遍历迭代器的,可遍历的对象是一个含有迭代器的对象,一般定义的object是没有自带迭代协议的也就是@@iterator方法,后面详细讲解此属性,Array、string、map等类型自带有这个属性,也就是本身就是可以被迭代的对象。

​  for in是遍历可枚举属性的,基本包装类型如Object,Array,Object的原型属性是不可以被枚举的,也就是说必须要自己定义的属性才可以被枚举,是否可以被枚举 通过Object.defineProperty()方法追加可枚举属性enumerable: true

  2.迭代协议

​    可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,例如,在一个 for..of 结构中,哪些值可以被遍历到。

​    要成为可迭代对象, 一个对象必须实现 @@iterator 方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator 访问该属性,比如object[Symbol.iterator]。

​    当一个对象需要被迭代的时候(比如被置入一个 for...of 循环时),首先,会不带参数调用它的 @@iterator 方法,然后使用此方法返回的迭代器获得要迭代的值。@@iterator 方法必须返回一个迭代器,如果不是使用迭代方法如扩展运算符或者for of会报错。

3.生成器

​    生成器对象是由一个 generator function 返回的,并且它符合可迭代协议迭代器协议,

    生成器函数GeneratorFunction永远返回一个生成器Generator).

​   基本使用方式:

Generator.prototype.next();

返回一个由 yield表达式生成的值。

Generator.prototype.return();

返回给定的值并结束生成器。

Generator.prototype.throw();

向生成器抛出一个错误。

    function * gen(){
        let index = 0;
        while(true){
            yield index++
        }
    }

    var g = gen()
    console.log(g.next())
    console.log(g.next())
    console.log(g.return())
    console.log(g.next())
/*
{ value: 0, done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
*/

4.迭代器、迭代协议和生成器的联系与区别

​    生成器是一个迭代器,迭代器不一定是生成器,可迭代对象包含了一个迭代协议@@iterator,同时生成器本身也是一个具有迭代协议的迭代器,可迭代对象可以使用扩展运算符和for...of进行迭代直到done:true,以下包含这段的具体说明:

  迭代器的定义和实现:

​ 只要实现了一个拥有以下语义(semantic)的 next() 方法,一个对象才能成为迭代器:

  1. next()方法是一个无参数函数

  2. next()方法返回一个对象包含donevalue两个属性

  3. done:如果迭代器可以产生序列中的下一个值,则为 false反之则为truevalue:迭代器返回的任何 JavaScript 值。

    由此可见迭代器其实只是实现了一个具有next()语义规则的方法,以下也算一个迭代器

    function myIterator() {
        let index = 0
        return {
           next: function () {
               if(index<5){
                   return {value:index++,done:false}
               }else{
                   return {value:undefined,done:true}
               } 
           }
        };
    }
    var iter = myIterator()
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())

    /*{ value: 0, done: false }
    { value: 1, done: false }
    { value: 2, done: false }
    { value: 3, done: false }
    { value: 4, done: false }
    { value: undefined, done: true }
    { value: undefined, done: true }*/

​ 迭代器也就是闭包的一种使用,只不过指定了规则,下面是使用生成器的迭代器: ​

    function * myIterator() {
        let index = 0
        while(index<5){
            yield index++
        }
    }
    var iter = myIterator()
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())
    console.log(iter.next())

/*
    { value: 0, done: false }
    { value: 1, done: false }
    { value: 2, done: false }
    { value: 3, done: false }
    { value: 4, done: false }
    { value: undefined, done: true }
    { value: undefined, done: true }*/

​ 下面是迭代协议的实现和运用:

    var Person = {
        name:"xiaoxiao",
        age:18,
        sexy:"girl"
    }
    console.log([...Person])
                                        //此时可见Person不是一个可迭代对象
    /* 
    console.log([...Person])
                    ^
    TypeError: Person is not iterable
    */

--------------------------------------------------------------------------------------
    var Person = {
        name:"xiaoxiao",
        age:18,
        sexy:"girl",

    }					//此时加上迭代协议的Person可以被扩展运算符迭代了

    Person[Symbol.iterator] = function(){
        let index = 0
        return{
            next:function(){
                if(index<5){
                    return {value:index++,done:false}
                }else{
                    return {value:undefined,done:true}
                }
            }
        }
    }
    console.log([...Person])

    //[ 0, 1, 2, 3, 4 ]