迭代器,可迭代对象,生成器函数

80 阅读4分钟

1,迭代器

/**
 * 什么是迭代器?
 *
 * 本质上是一个对象,符合迭代器协议iterator protocal
 *
 * 迭代器协议:
 * 返回一个next方法,调用next方法返回一个对象,包含done和value属性
 * done:boo,取决于迭代是否完成
 * value:any,可以返回JS中的任何值
 */
/**
 * 1,基本实现
 *
 * 弊端:不符合高内聚思想,index和iterator是一个整体但是分离,没有封装只能多次复用不够优雅
 */

let index = 0
const animal = ["cat", "dog", "fish"]

const iterator = {
  next() {
    if (index < animal.length) {
      return {
        done: false,
        value: animal[index++],
      }
    } else {
      return {
        done: true,
        value: undefined,
      }
    }
  },
}
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
/**
 * 2,封装实现
 * 高内聚性高,减少复用和冗余
 */

function myIterator(arr) {
  let index = 0
  return {
    next() {
      if (index < arr.length) {
        return {
          done: false,
          value: arr[index++],
        }
      } else {
        return {
          done: true,
          value: undefined,
        }
      }
    },
  }
}
const res = myIterator(["cat", "dog", "fish"])
console.log(res.next())
console.log(res.next())
console.log(res.next())
console.log(res.next())

2.可迭代对象

/**
 * 可迭代对象
 *
 * 本质上是一个对象,符合可迭代对象协议
 *
 * 可迭代对象协议:
 * - 实现了[Symbol.iterator]为方法,这个方法返回一个迭代器对象
 * - forof本质上就是调用这个函数,也就是[Symbol.iterator]
 */

2.1.JS内置的原生可迭代对象

/**
 * JS内置的原生可迭代对象:
 * arr,set,map,string字符串,argument,dom对象的Nodelist
 */
/**
 * 查看Symbol.iterator
 */
const str = "one"
const ite = str[Symbol.iterator]()
console.log(ite.next()) // { value: 'o', done: false }
console.log(ite.next()) // { value: 'n', done: false }
console.log(ite.next()) // { value: 'e', done: false }
console.log(ite.next()) // { value: undefined, done: true }

2.2.可迭代对象的实现/应用

/**
 * 可迭代对象的实现
 *
 * 可迭代对象的应用:
 * forof
 * 解构
 * promise.all/promise.race
 * Arrary.from
 */
const p1 = {
  value: "abc",
  [Symbol.iterator]: function () {
    let index = 0
    let _this = this
    return {
      next() {
        if (index < _this.value.length) {
          return {
            done: false,
            value: _this.value[index++],
          }
        } else {
          return {
            done: true,
            value: undefined,
          }
        }
      },
    }
  },
}

for (const iterator of p1) {
  console.log(iterator)
}

2.3.类迭代的实现

class Person {
  constructor(name, animal) {
    this.name = name
    this.animal = animal
  }
  [Symbol.iterator]() {
    let index = 0
    let _this = this
    return {
      next() {
        if (index < _this.animal.length) {
          return {
            done: false,
            value: _this.animal[index++],
          }
        } else {
          return {
            done: true,
            value: undefined,
          }
        }
      },
    }
  }
}
const p2 = new Person("p2", ["cat", "fish", "dog"])
for (const iterator of p2) {
  console.log(iterator)
}

3.生成器函数

/**
 * 生成器函数
 *
 * 和普通函数的不同
 * - function*
 * - 通过yield控制函数的暂停\继续
 * - 返回一个generator生成器,是一个特殊的迭代器
 */

3.1.使用,单次执行,多次执行

/**
 * 1.使用
 *
 * 没有执行,∵它是一个生成器函数,返回一个生成器,是一个特殊的迭代器
 */
function* run1() {
  console.log("run1")
}
run1()



/**
 * 2.单次执行
 */
function* run2() {
  console.log("run2")
}
const generator2 = run2()
console.log(generator2.next()) //run2, {value: undefined, done: true}



/**
 * 3.多次执行
 */

function* run3() {
  console.log("run3 start")
  yield 1
  console.log("run3 run")
  yield 2
  console.log("run3 end")
  return 3
}
const generator3 = run3()
console.log(generator3.next()) // {value: 1, done: false}
console.log(generator3.next()) // {value: 2, done: false}
console.log(generator3.next()) // {value: 3, done: true}
console.log(generator3.next()) // {value: undefined, done: true}

3.2.分段传参

/**
 * 4.分段传参
 * ∵生成器函数是可以分段执行的,∴可以尝试分段传参abc
 *
 * 缺点:可读性差
 * 优点:可以处理异步操作
 *
 * 第一次传参在调用run的时候
 * 第一次next,到yield暂停,返回a
 * 第二次next,yield开始执行左边的代码const res1 = 传入的值,到下一行的yield暂停,返回ba
 * 第三次next,yield开始,const res2 = c,返回cba,迭代完成
 */
 
function* run(params) {
  console.log(params)
  const res1 = yield params
  const res2 = yield res1 + params
  return res2 + res1 + params
}
const generator = run("a")
console.log(generator.next()) // { value: 'a', done: false }
console.log(generator.next("b")) // { value: 'ba', done: false }
console.log(generator.next("c")) //  { value: 'cba', done: true }
console.log(generator.next()) // { value: undefined, done: true }

3.3.生成器替代迭代器,类迭代,可迭代对象的终极封装

/**
 * 生成器替代迭代器
 *
 * 语法糖yield*:遍历可迭代对象
 */

let animal = ["dog", "cat", "fish"]

// 迭代器的封装实现
function myIterator(params) {
  let index = 0
  return {
    next() {
      if (index < params.length) {
        return { done: false, value: params[index++] }
      } else {
        return { done: true, value: undefined }
      }
    },
  }
}

const iterator = myIterator(animal)
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

// 生成器替代迭代器
// function* myIterator2(params) {
//   for (const iterator of params) {
//     yield iterator
//   }
// }

// 语法糖
function* myIterator2(params) {
  yield* params
}

const iterator2 = myIterator2(animal)
console.log(iterator2.next())
console.log(iterator2.next())
console.log(iterator2.next())
console.log(iterator2.next())
/**
 * 类迭代,可迭代对象的终极封装
 */

// 类迭代
class Person {
  constructor(name, animal) {
    this.name = name
    this.animal = animal
  }
  *[Symbol.iterator]() {
    yield* this.animal
  }
}

const A = new Person("a", ["cat", "fish", "dog"])
for (const iterator of A) {
  console.log(iterator)
}

// 可迭代对象
const p1 = {
  value: "abc",
  *[Symbol.iterator]() {
    yield* this.value
  },
}

for (const iterator of p1) {
  console.log(iterator)
}

4.总结

/**
 * 迭代器
 * 本质上是一个对象,符合迭代器协议
 * 内部实现一个next方法,调用next返回一个对象,包含value,done
 *
 *
 * 可迭代对象
 * 本质上是一个对象,符合可迭代对象协议
 * 内部实现[Symbol.iterator]方法,调用方法返回一个迭代器
 *
 *
 * 生成器
 * 用function*定义,yield控制函数的暂停继续,返回一个生成器generator,是一个特殊的迭代器
 */