迭代器和可迭代协议
迭代和遍历的区别
类似于遍历
遍历:有多个数据组成的集合数据结构(map,set,array 等其他类数组),需要从该结构一次取出数据进行某种处理
迭代:按照某种逻辑,一次取出下一个数据进行处理,不要求是数组等类数组,但数组类数组一定可以迭代
迭代器
JS 语言规定:如果一个对象具有 next 方法,并且 next 方法满足一定的约束,则该对象是一个迭代器
next 方法的约束:该方法必须返回一个对象,该对象返回两个属性:
- value:any 类型,下一个数据的值
- done:bool 类型,是否已经迭代完成
通过迭代器的 next 方法 ,可以依次取出数据,并可以根据返回的 done 属性,判定是否迭代结束
迭代器创建函数,iterator creator
它是指一个函数,调用该函数后,返回一个迭代器,则该函数称之为迭代器创建函数,可以简称迭代器函数
// 迭代器创建函数
function createIterator(total){
let i=0//当前迭代次数
return{
next(){
i++
return { //当前这一次迭代的数据
value:i>total?undefined :i,
done:i>total
}
}
}
}
var iterator=createIterator(5)
let next=iterator.next()
while (!next.done) {
console.log(next.value);
next=iterator.next()
}
可迭代协议
ES6 中出现了 for-of 循环,该循环就是用于迭代某个对象的,因此,for-of 循环要求对象是可迭代的(对象必须满足可迭代协议)
可迭代协议是用于约束一个对象的,如果一个对象满足下面的规范,则该对象满足可迭代协议,该对象就是可迭代对象
可迭代协议约束如下:
- 对象必须有一个知名符号属性(Symbol.iterator)
- 该属性必须是一个无参的迭代器创建函数
for-of 循环的原理
调用对象的 Symbol.iterator 属性方法,得到一个迭代器,不断调用 next 方法,只有返回的 done 为 false,则将返回的 value 传递给变量,然后进入循环体执行一次
let obj = {
// 可迭代对象必须有一个[Symbol.iterator]属性,并且属性是一个无参数的迭代器创建函数
[Symbol.iterator]: () => {
let total = 3
let i = 0
return {
next() {
i++
return {
value: i,
done: i > total,
}
},
}
},
}
// 可迭代对象会把value赋值给item,一直next(),直到done为true
for (item of obj) {
console.log(item)
}
// for of 循环实际是做了如下的事情
let iterator = obj[Symbol.iterator](3)
let result = iterator.next()
while (!result.done) {
const item = result.value
console.log(item)
result = iterator.next()
}
迭代器实现斐波那契数
// 迭代器实现斐波那契数(1,1,2,3,5,8.....)
var iterator = {
a: 1,
b: 1,
currentIndex: 0,
next() {
this.currentIndex++
var c = this.a + this.b
this.a = this.b
this.b = c
if (this.currentIndex === 1 || this.currentIndex === 2) {
return {
value: 1,
done: this.currentIndex>5, //定义为第五个斐波那契数停止迭代
// done: false,
}
}
return {
value: c,
done: this.currentIndex > 5,
}
},
}
let next = iterator.next()
while (!next.done) {
next = iterator.next()
}
console.log(next.value) //第5个数的值