开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
前言
之前对生成器,迭代器学的比较模糊,最近开始重新复习了一下,学习的总结内容在这分享给大家,欢迎相互学习,共同进步!
一. 什么是迭代器?
迭代器是确保用户可以在容器对象(如链表、数组)上访问对象,不需要关注对象内部实现。简单来说其就是帮助我们对某个数据结构进行遍历的对象。迭代器迭代器是一个具体的对象,这个对象需要符合迭代器协议(iterator protocol),即定义了产生一系列值的标准方式,在js中用next方法。
next方法:一个无参数或者一个参数的函数,返回一个必须拥有两个属性对象:done(boolean)和value。
举例:
const names = ["hh", "kk", "oo"]
// 创建一个迭代器对象来访问数组
let index = 0
const Iterator = {
next: function() {
if (index < names.length) {
return { done: false, value: names[index++] }
} else {
return { done: true, value: undefined }//可省略,不能迭代后默认返回undefined
}
}
}
console.log(Iterator.next())
console.log(Iterator.next())
console.log(Iterator.next())
console.log(Iterator.next())
console.log(Iterator.next())
由上可知:迭代器如果迭代完毕,done为true,value为undefined,当然其可省略,省略的话就是返回undefined
1. 迭代器函数
我们可以创建迭代器函数,传入可迭代的数组进行迭代,当然可以创建无限的迭代器。
举例:
function createArrayIterator(arr) {
let index = 0
return {
next: function() {
if (index < arr.length) {
return { done: false, value: arr[index++] }
} else {
return { done: true, value: undefined }
}
}
}
}
const nums = [10, 22, 33, 12]
const numsIterator = createArrayIterator(nums)
console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())
console.log(numsIterator.next())
//一个无限的迭代器
function createNumberIterator() {
let index = 0
return {
next: function() {
return { done: false, value: index++ }
}
}
}
2.可迭代对象
一个对象满足可迭代,就必须实现可迭代的方法,在代码中我们使用Symbol.iterator访问属性。
举例:
// 创建一个iterableObj迭代器对象来访问数组
const iterableObj = {
names: ["hh", "kk", "oo"],
[Symbol.iterator]: function() {
let index = 0
return {
next: () => {
if (index < this.names.length) {
return { done: false, value: this.names[index++] }
} else {
return { done: true, value: undefined }
}
}
}
}
}
const iterator = iterableObj[Symbol.iterator]()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
通常我们for.. of遍历的对象就是可迭代对象。js中内置的迭代对象有:Stirng、Array、Map、Set、arguments对象、NodeList集合。
举例:
const names = ["abc", "cba", "nba"]
console.log(names[Symbol.iterator]) // [Function: values]
// const iterator1 = names[Symbol.iterator]()
// console.log(iterator1.next())
// console.log(iterator1.next())
// console.log(iterator1.next())
// console.log(iterator1.next())
for (const item of names) {
console.log(item)
}
// Map/Set
const set = new Set()
set.add(10)
set.add(100)
set.add(1000)
console.log(set[Symbol.iterator])//[Function: values]
for (const item of set) {
console.log(item)
}
// 函数中arguments也是一个可迭代对象
function foo(x, y, z) {
console.log(arguments[Symbol.iterator]) //[Function: values]
for (const arg of arguments) {
console.log(arg)
}
}
foo(10, 20, 30)
可迭代对象应用于:
- JavaScript中语法:for ...of、展开语法、yield*(生成器)、解构赋值;
- 创建一些对象:new Map([Iterable])、new WeakMap([iterable])、new Set([iterable])、new WeakSet([iterable]);
- 一些方法的调用:Promise.all(iterable)、Promise.race(iterable)、Array.from(iterable);
举例:
names=[1,23,33]
//展开运算符
const newNames = [...names, ...iterableObj]
//解构语法
const [ name1, name2 ] = names
// 一些对象
const set1 = new Set(iterableObj)
const set2 = new Set(names)
const arr1 = Array.from(iterableObj)
// Promise.all
Promise.all(iterableObj).then(res => {
console.log(res)
})
三. 自定义类迭代器
上方我们知道Array、Set、String、Map等类创建出来的对象是可迭代对象,然而我们也可以自己自定义一个类,让其创建的对象都是可迭代的。
举例:
class Classroom {
constructor(address, name, students) {
this.address = address
this.name = name
this.students = students
}
add(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("中山路", "前端", ["james", "kobe"])
classroom.add("lilei")
for (const stu of classroom) {
console.log(stu)
// if (stu === "kobe") break // 也可以break 终止迭代
}
总结
学完这个大家可点击该链接,学习一些生成器一种特殊的迭代器。