迭代器学习
什么是迭代器
- 迭代器,是用户在容器对象(container,例如链表或数组)上遍访的对象,使用该接口无需关心对象的内部实现细节。
- 其行为像是数据库中的光标,各种编程语言都有迭代器,例如Java、Python。
- 迭代器的作用是帮助我们对某个数据结构进行遍历的对象。
在JavaScript中,迭代器是一个具体的对象,这个对象需要符合迭代器协议。
- 迭代器协议定义了产生一系列值(无论是有限还是无限个)的标准方式;
- 在JavaScript中这个标准就是一个特定的next方法;
next方法的要求
一个无参数或者一个参数的函数,fanUI一个拥有一下两个属性的对象:
done (boolean)
- 如果迭代器可以先生序列中的下一个值,则为false
- 如果迭代器已将序列迭代完毕,则为TRUE。在这种情况下,value是可选的,如果它依然存在,即为迭代结束之后的默认返回值。
value
- 迭代器返回的任何JavaScript值。done为TRUE时可省略
const friends = ["1","2","3","4"]
let index = 0
const friendIterator = {
next: function (){
if (index < friends.length) {
return {
value: friends[index++],
done: false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
console.log(friendIterator.next()) //{ value: '1', done: false }
console.log(friendIterator.next()) //{ value: '2', done: false }
console.log(friendIterator.next()) //{ value: '3', done: false }
console.log(friendIterator.next()) //{ value: '4', done: false }
console.log(friendIterator.next()) //{ value: undefined, done: true }
const friends = ["1","2","3","4"]
let index = 0
function createArrayIterator(arr) {
return {
next: function (){
if (index < arr.length) {
return {
value: arr[index++],
done: false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
}
const friendIterator = createArrayIterator(friends)
console.log(friendIterator.next()) //{ value: '1', done: false }
console.log(friendIterator.next()) //{ value: '2', done: false }
console.log(friendIterator.next()) //{ value: '3', done: false }
console.log(friendIterator.next()) //{ value: '4', done: false }
console.log(friendIterator.next()) //{ value: undefined, done: true }
可迭代对象
当一个对象实现了iterable protocol协议是,它就是一个可迭代对象
这个对象的要求是必须实现 @@iterator方法,在代码中使用Symbol.iterator访问该属性;
可迭代对象的好处
- 当一个对象变成可迭代对象的时候,他就可以进行某些迭代操作;
- 例如 for...of操作时,其实就会调用它的 @@iterator方法
可迭代对象代码:
const info = {
friends: ['lisi', 'wangwu', 'zhangsan'],
[Symbol.iterator]: function () {
let index = 0;
return {
next: function () {
if (index < this.friends.length) {
return {
value: this.friends[index++],
done: false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
}
}
原生迭代器对象
事实上我们平时创建的很多原生对象已经实现了可迭代协议,会生成一个迭代器对象的:
- String、Array、Map、Set、arguments对象、NodeList集合;
// 数组本身是一个可迭代对象
let nums = [0, 1, 0, 3, 12]
// 获取可迭代的函数
console.log(nums[Symbol.iterator]) // console.log(nums)
// 调用可迭代函数,获取到迭代器
const iterator = nums[Symbol.iterator]()
console.log(iterator.next())//{ value: 0, done: false }
console.log(iterator.next())//{ value: 1, done: false }
console.log(iterator.next())//{ value: 0, done: false }
console.log(iterator.next())//{ value: 3, done: false }
console.log(iterator.next())//{ value: 12, done: false }
console.log(iterator.next())//{ value: undefined, done: true }
可迭代对象的应用
那么这些东西可以被用在哪里呢?
- JavaScript中语法:for ...of、展开语法(spread syntax) 、yield* 、解构赋值 (Destructuring_assignment)
- 创建一些对象时:new Map([Iterable]) 、new WeakMap([iterable]) 、new Set([iterable]) 、new WeakSet([iterable])
- 一些方法的调用:Promise.all(iterable) 、Promise.race(iterable) 、Array.from(iterable)
自定义类的迭代
- 在面向对象开发中,我们可以通过class定义一个自己的类,这个类可以创建很多的对象
- 如果我们希望自定义的类创建的对象默认是可迭代,那么在设计类的时候我们可以添加上@@iterator方法
案例
- 教室中有自己的位置、名称、当前教室的学生;
- 这个教室可以进来新学生
- 创建的教室是可迭代对象
class Classroom {
constructor(name, address, initialStudent) {
this.name = name;
this.address = address;
this.students = initialStudent;
}
push(student) {
this.students.push(student);
}
[Symbol.iterator]() {
let index = 0
return {
next: () => {
if (index < this.students.length) {
return {value: this.students[index++], done: false}
} else {
return {value: undefined, done: true}
}
}
}
}
}
const classroom = new Classroom("三年级1班", "思源楼301室", ["小红", "小白", "小黄"])
const classroom1 = new Classroom("三年级2班", "思源楼302室", ["小蓝", "小绿", "小青"])
for (const stu of classroom1) {
console.log(stu)
}
for (const stu of classroom) {
console.log(stu)
}
迭代器的终端
迭代器在某些情况下会在没有完全迭代的情况下中断:
- 比如遍历的过程中通过break、return、throw中断了循环操作;
- 比如在解构的时候,没有解构所有值;