一、认识什么是迭代器
迭代器协议定义了一系列值(无论有限个还是无限个)的标准方式,当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。
// 编写的一个迭代器对象
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)
}
总结
用得少但是可以了解一下。