Javascript之迭代器与生成器


一、认识什么是迭代器

迭代器协议定义了一系列值(无论有限个还是无限个)的标准方式,当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。

// 编写的一个迭代器对象
const iterator = {
 next: function() {
  return {
   done: true,
   value: 123
  }
 }
}


// 定义一个数组
const names = ['abc', 'cba', 'nba']

// 创建一个迭代器对象来访问数组
let index = 0
const nameIterator = {
 next: function() {
   if(index < name.length) {
    return { done: false, value: names[index++] }
  } else {
    return { done: true, value: undefined }
  }
 }
}

console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
console.log(nameIterator.next())
// 输出
{ done: false, value: 'abc' }
{ done: false, value: 'cba' }
{ done: false, value: 'nba' }
{ done: true, value: undefined }
// 一旦done为true,那就意味着这个生成器当前要生成的代码生成结束了

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

二、自定义类的可迭代性

需求:创建一个教室类,创建出来的对象都是可迭代对象

// 首先创建一个类
class Classroom {
 constructor(address,name,students) {
    this.addresss = address
    this.name = name
    this.students = students
 }

  // 新增一些学生
  entry(newStudent) {
  this.students.push(newStudent)
 }
 
 //
 [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 }
   }
  }
 }

}


const classroom = new Classroom('3幢5楼','计算机教室', ['james', 'kobe', 'curry', 'why'])

classroom.push('lilei')

for (const item of classroom) {
 console.log(item) // 输出:james kobe curry why lilei
 // 可通过break终止迭代器
  if (item === 'why') break
}

三、什么是生成器 

1、生成器是ES6中新增的一种函数控制、使用的方案,它可以让我们更加灵活的控制函数什么时候执行、暂停执行等。

2、生成器函数也是一个函数,但是和普通的函数有一些区别:

首先,生成器函数需要在function后面加一个符号: *

其次,生成器函数可以通过yield关键字来控制函数的执行流程

最后,生成器函数等返回值是一个Generator(生成器):生成器事实上是一种特殊的迭代器。

// 定义一个生成器函数 
function* foo() {
 console.log('函数开始执行')
 
 const value1 = 100
 console.log(value1)
 yield

 const value2 = 200
 console.log(value2)
 yield

 const value3 = 300
 console.log(value3)
 yield

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

// 调用生成器函数时,会给我们返回一个生成器对象
const generator = foo()


// 通过next()分段执行调用
// 开始执行第一段代码
generator.next()

// 开始执行第二段代码
generator.next()

3、生成器函数等执行流程 

// 当遇到yield时候是暂停函数的执行
// 当遇到return的时候生成器就停止执行
function* foo() {
 console.log('函数开始执行')
 
 const value1 = 100
 console.log('第一段代码',value1)
// return以后的就不会继续执行了
// return value1

 console.log('继续执行的代码')

// 如果想返回值,可以通过yield,譬如
// yield value1
 yield

 const value2 = 200
 console.log('第二段代码',value2)
 yield

 const value3 = 300
 console.log('第三段代码',value3)
 yield

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


// generator本质上是一个特殊的iterator
const generator = foo()
console.log('返回值1:',generator.next())
console.log('返回值2:',generator.next())
console.log('返回值3:',generator.next())
console.log('返回值4:',generator.next())


4、生成器的其他方法使用 

// 暂停函数的时候 需要有返回值
function* 100(num) {
  console.log('函数开始执行')

  const value1 = 100 *num
  console.log('第一段代码:',value1)
  const n = yield value1


  const value2 = 200 *n
  console.log('第一段代码:',value2)
  const count = yield value2


  const value3 = 300 *count
  console.log('第一段代码:',value3)
  yield value3
}

const generator = foo()
console.log('返回值1:',generator.next())
console.log('返回值2:',generator.next())
console.log('返回值3:',generator.next())
console.log('返回值4:',generator.next())

5、生成器替代迭代器使用 

// 1、生成器来替代迭代器
function* createArrayIterator(arr) {

 //第一种写法
 // yield 'abc' // 输出 { done: false, value: 'abc' }
 // yield 'cba' // 输出 { done: false, value: 'cba' }
 // yield 'nba' // 输出 { done: false, value: 'nba' }

 // 第二种写法
 // for (const item in arr) {
 //  yield item
 // }

 // 第三种写法
 // yield* 只适用可迭代对象
 yield* arr
}
 
const names = ['abc','cba', 'nba']

const nameIterator = createArrayIterator(names)

console.log(nameIterator.next())

// 2、创建一个函数,这个函数可以迭代一个范围内的数组
// 譬如10 20
function createRangeIterator(start, end) {
// 第一种写法
// let index = start
// return {
// next: function() {
//  if(index < end) {
//    return { done: false, value: index++ }
//   } else {
//    return { done: true, value: undefined}
//   }
//  }
// }


// 第二种写法
  let index = start
  while(index < end) {
   yield index++
  }
}

const rangeIterator = createRangeIterator(10,20)
console.log(rangeIterator.next())


// 3、class案列
class Classroom {
 constructor(address,name,students) {
    this.addresss = address
    this.name = name
    this.students = students
 }

  // 新增一些学生
  entry(newStudent) {
  this.students.push(newStudent)
 }
 
 
 foo = function() {
  console.log('foo function')
 }

 *[Symbol.iterator]() {
   // 依次把需要返回的学生返回出去
   yield* this.students
  }

}

const classroom - new Classroom('3幢', '1102', ['abc', 'cba'])
// classroom.foo()

for (const item of classroom) {
 console.log(item)
}


总结

用得少但是可以了解一下。

猜你喜欢

转载自blog.csdn.net/vanora1111/article/details/126494565