迭代器和生成器

x33g5p2x  于2022-03-11 转载在 其他  
字(5.3k)|赞(0)|评价(0)|浏览(220)

一、迭代器

1.1、认识迭代器
迭代器就是通过迭代器调用next方法,让指针指向下一位,从而遍历全部内容。

let names = ['dmc', 'dl', 'dxn', 'dsm', 'djm']

let index = 0
let IteratorObject = {
  next() {
    if (index < names.length) {
      return {
        done: false,
        value: names[index++]
      }
    } else {
      return {
        done: true,
        value: undefined
      }
    }
  }
}

console.log(IteratorObject.next())
console.log(IteratorObject.next())
console.log(IteratorObject.next())
console.log(IteratorObject.next())
console.log(IteratorObject.next())
console.log(IteratorObject.next())
console.log(IteratorObject.next())

如上图所示就是一个迭代器,我们通过调用next函数就可以遍历数组中的所有元素。
1.2、迭代器函数
我们可以向迭代器函数中传入一个可迭代对象,这样就得到一个迭代器。

const InteratorFun = function (arr) {
  let len = arr.length
  let index = 0
  return {
    next() {
      if (index < len) {
        return {
          done: false,
          value: arr[index++]
        }
      } else {
        return {
          done: true,
          value: undefined
        }
      }
    }
  }
}

let arr = ['dmc', 'dl', 'dxn', 'djm', 'csm']
let createArrFun = InteratorFun(arr)
console.log(createArrFun.next())
console.log(createArrFun.next())
console.log(createArrFun.next())
console.log(createArrFun.next())
console.log(createArrFun.next())
console.log(createArrFun.next())

1.3、可迭代对象
就是存在[Symbol.iterator]的对象

const num = {
  names: ['dmc','dl', 'dxn', 'djm', 'csm'],
  [Symbol.iterator]: function() {
    let index = 0
    return {
      next: () =>  {
        if(index < this.names.length) {
          return {
            done: false,
            value: this.names[index++]
          }
        }else {
          return {
            done: true,
            value: undefined
          }
        }
      }
    }
  }
}
let inter = num[Symbol.iterator]()
console.log(inter.next())
console.log(inter.next())
console.log(inter.next())
console.log(inter.next())
console.log(inter.next())
console.log(inter.next())
console.log(inter.next())

//此时也可以使用for...of来进行迭代
for(let i of num) {
  console.log(i)
}

1.4、内置可迭代对象
内置可迭代对象说明内部存在[Symbol.iterator]的对象

//数组
const arr = [1, 2, 3]
for (const item of arr) {
  console.log(item)
}
//字符串
const str = '1234567'
for (let i of str) {
  console.log(i)
}

//函数中的可迭代对象
function foo() {
  for (let item of arguments) {
    console.log(item)
  }
}
foo('sz', 'sf', 'cs', 'df')

1.5、可迭代对象的应用场景

1、使用for...of可以循环遍历
2、使用解构(指的是数组的解构,对象的解构利用的不是可迭代对象,对象的解构利用的是es9中新增的语法)。
3、展开运算符(数组的展开运算符,es9中新增的对象展开运算符,和迭代器无关)。
4、可以创建新的迭代对象,set类型的数据,其中的参数必须是可迭代对象,如果向其中传入number类型的数据,就会报错。
5、Promise.all()中必须传入可迭代对象。

1.6、自定义可迭代类
(一般来说,类是不可以迭代的,但是我们知道一个可迭代对象中一定存在)[Symbol.iterator]()方法, 下面我们自己实现可迭代类。

class ClassRoom {
  constructor(name, place, students) {
    this.name = name
    this.place = place
    this.students = students
  }

  [Symbol.iterator]() {
    let index = 0
    return {
      next: () => {
        if (index < this.students.length) {
          return {
            done: false,
            value: this.students[index++]
          }
        } else {
          return {
            done: true,
            value: undefined
          }
        }
      },
      return () { //如果意外终止,则会触发return方法
        console.log('意外终止了')
        return {
          done: true,
          value: undefined
        }
      }
    }
  }
}

let c1 = new ClassRoom('dl', '计算机2019', ['dmc', 'dxn', 'djm', 'csm'])
for(let i of c1) {
  console.log(i)
  if(i === 'dxn') {
    break
  }
}

二、生成器

2.1、生成器函数

1、生成器函数也是函数,只不过生辰器函数存在特殊的样式 function* ()。
2、生成器函数的返回值是一个生成器。
3、生成器函数可以通过yield来控制函数执行流程。
4、生辰器是特殊的迭代器。

2.2、基本使用

function* foo() {
  console.log('函数开始执行')
  const num1 =100
  console.log(num1)
  yield

  const num2 = 200
  console.log(num2)
  yield

  const num3 = 300
  console.log(num3)
  yield

  console.log('函数执行结束')
}

let generator = foo()
generator.next()
generator.next()
generator.next()
generator.next()

如上述代码所示:返回值generator是一个生成器,通过不断地调用next来控制执行流程。
2.3、执行流程

function* foo() {
  console.log('函数开始执行')
  const num1 =100
  console.log(num1)
  yield  num1 * 100

  const num2 = 200
  console.log(num2)
  yield num2 * 100

  const num3 = 300
  console.log(num3)
  yield num3 * 100

  console.log('函数执行结束')
}

let generator = foo()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())

如上所示,需要执行4步,执行到yield就停止,将yield后面的值作为返回值,格式和迭代器一样。
2.4、生成器函数的next传参

function* foo(num) {

  const value1 = 1
  const n = yield value1 * 100 * num

  const value2 = 10 * n
  yield value2 * 200

  console.log('函数执行结束.')
}

let generator = foo(100)
console.log(generator.next())
console.log(generator.next(200))

我们可以向生成器的next方法传入参数,其值可以作为yield左边的值。
2.5、生成器函数的return方法

function* foo(num) {

  const value1 = 1
  const n = yield value1 * 100 * num

  const value2 = 10 * n
  yield value2 * 200

  console.log('函数执行结束.')
}

let generator = foo(100)
console.log(generator.return('哈哈哈哈哈'))
console.log(generator.next(200))
console.log(generator.next(200))

2.6、生成器函数中不仅可以传入参数,也可以抛出异常

function* foo() {
  console.log('函数开始执行.')

  const value1 = 1
  try {
    yield value1 * 100
  } catch (err) {
    console.log(err)
  }

  const value2 = 10 
  yield value2 * 200

  console.log('函数执行结束.')
}
const generatorFun = foo()
console.log(generatorFun.next())
console.log(generatorFun.throw('这里是错误信息'))  //会在第一次执行完,传入值就是报错信息,会被catch捕获到
/**
 *在这里报错
 *   const n = yield value1 * 100
            ^
*/

2.6、用生成器来代替迭代器

function* createArrInterator(arr) {
  yield* arr
}

let interator = createArrInterator(['111', '222', '333'])
console.log(interator.next())
console.log(interator.next())
console.log(interator.next())
console.log(interator.next())
console.log(interator.next())
/**
{ value: '111', done: false }
{ value: '222', done: false }
{ value: '333', done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
 * **/

2.8、用生成器来迭代数字

function* createNumber(a, b) {
  while(a < b) {
    yield a++
  }
}

let num = createNumber(10,20)
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())

2.9、使用生成器来代替迭代器生成class的迭代对象

function* createNumber(a, b) {
  while(a < b) {
    yield a++
  }
}

let num = createNumber(10,20)
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())
console.log(num.next())

相关文章

微信公众号

最新文章

更多