迭代器
迭代器是一个具体的对象,他需要符合 迭代器协议
迭代器协议:对象中要求有一个 next 函数,这个next() ,只能没有参数或者有一个参数 ,而且需要返回一个 带有 { done:false/ true,value: xxx }的对象
如果迭代器可以产生下一个值的话,那么 done:false
如果迭代完成的话,done 会变为 true
const arr1 = [10,15,58,52]
let i = 0
const iterator = {
next:function(){
if( i < arr1.length ){
return { done : false , value : arr1[i++] }
}else {
return {done : true , value : undefined}
}
}
}
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
可迭代对象
当一个对象实现可迭代协议的时候,它就是可迭代对象
在代码中我们使用 Object.iterator 访问该属性
const obj = {
arr1: [10, 15, 89, 25],
[Symbol.iterator]: function () {
let index = 0;
// console.log(index,'-----');
return {
next: () => {
if (index < this.arr1.length) {
//为了能够访问到 arr1,要将arr1 改为 this.arr1 ,函数改为箭头函数
return { done: false, value: this.arr1[index++] };
} else {
return { done: true, value: undefined };
}
},
};
},
};
const iterator1 = obj[Symbol.iterator](); //得到的是一个对象
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
迭代器对象的作用:使用for of 遍历对象的时候,就是取迭代器对象里面的值 .value
不停的调用 next(),然后取到 里面的 value
内置创建可迭代对象
String、array 、Set 、Map 、arguments对象等
里面内部都是自带可迭代对象的
可迭代对象的应用
for of 语法 、 展开运算符 、 解构运算符 、new Map( iterator )、new Set( iterator ) 、promise.all()
使用for of 语法的时候,是不断的的调用next(),然后获取里面的value值
展开运算符,也可以传递可迭代对象,取到里面Value的值,然后给新数组赋值
对象的展开运算是采用了别的方法,对里面的键值对进行遍历,然后给新的对象赋值
对象的解构赋值,也是采用了别的方式
迭代器在类中的使用
类方法正常来说是不能通过迭代器进行遍历的,但是可以给类加上 [Symbol.iterator] 方法
class classRoom{
constructor(address,students){
this.address = address
this.students = students
}
entry(newStudents){
this.students.push(newStudents)
}
[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}
}
}
}
}
}
const p1 = new classRoom('重庆',['aaa','bbb','ccc'])
for (const item of p1){
console.log(item)
}
生成器函数
生成器函数需要在function 后面 + *
生成器函数可以通过yield 来控制函数的暂停和执行
生成器函数的返回值是一个 生成器
生成器是一种特殊的迭代器
function* Gen (){
console.log('这是个生成器')
let value1 = 100
console.log('value1:',value1)
const n = yield value1 //接收调用函数时传递进来的参数
console.log('-------')
value1 = 200 * n
console.log('value2:',value1)
yield
console.log('-------')
value1 = 300
console.log('value3:',value1)
yield
console.log('函数结束咯')
}
Gen() //直接执行函数没有任何输出
const gen = Gen()
console.log( gen.next() ) //执行第一个 yield往上的内容
console.log( gen.next(2) ) //执行第二个 yield往上的内容
console.log( gen.next() ) //执行第三个 yield往上的内容
console.log( gen.next() ) //执行最后的全部内容
value1: 100
结果:
这是个生成器
VM222:4 value1: 100
VM222:21 {value: 100, done: false}
VM222:7 -------
VM222:9 value2: 400
VM222:22 {value: undefined, done: false}
VM222:12 -------
VM222:14 value3: 300
VM222:23 {value: undefined, done: false}
VM222:17 函数结束咯
VM222:24 {value: undefined, done: true}
如果想要value里面有值的话,要通过 yield 后面加上值
传参
如果想要给后续的函数传递参数的话,要在第二个 gen.next() 里面加上参数,可以在上一个 yield里面接收到传递的参数
const n = yield
生成器的return方法
Gen.return() 当调用这个方法的时候,后续的方法调用 会返回 { done:true ,value:undefined } 的状态
console.log( gen.next() ) //执行第一个 yield往上的内容
Gen.return() 方法,上面的函数会正常执行,下面的函数不会正常执行,会返回
{ done:true ,value:undefined }
console.log( gen.next(2) ) //执行第二个 yield往上的内容 console.log( gen.next() ) //执行第三个 yield往上的内容 console.log( gen.next() )
生成器的throw方法
使用生成器的 throw 方法抛出异常,会给 yield 方法报错,可以使用 try ... catch 方法进行错误捕获
生成器代替迭代器
生成器代替迭代器,我们可以使用 yield 传入可迭代对象
//方法1
function* Gen (arr){
for(const item of arr){
yield item
}
}
//我们调用 Gen函数通过往里面传入数组,遍历里面的元素,然后通过 yield就可以实现迭代器的功能
const names = ['aaa','bbb','ccc']
const foo = Gen2(names)
console.log(foo.next());
console.log(foo.next());
console.log(foo.next());
console.log(foo.next());
结果:/*
{ value: 'aaa', done: false }
{ value: 'bbb', done: false }
{ value: 'ccc', done: false }
{ value: undefined, done: true }
*/
//方法2
function* Gen(arr){
yield* arr
}
```结果同上```
我们通过调用yield* 的时候,要传入 可迭代对象,yield* 会自动迭代然后将数据传出
// 方法3 ,在类中使用生成器
class Classroom {
constructor(address,students){
this.address = address
this.studentd = students
}
[Symbol.iterator] = function* (){
// for(const item of this.students){
//}
yield* this.students
}
}
const p1 = new Classroom('重庆',['aaa','bbb','ccc'])
//让类具有可迭代对象,就可以使用 for... of 进行遍历