JS中的迭代器、可迭代对象、生成器
创始人
2024-04-09 01:53:16
0

迭代器

迭代器(iterator),是使用户在容器对象(container,例如链表或数组)上可以遍历访问的对象,使用该接口无需关心容器对象的内部实现细节。 

从上面定义上来看,迭代器是帮助我们对某个数据结构进行遍历的对象

迭代器本身也是一个具体的对象,只不过这个对象需要符合迭代器协议,通俗的讲就是该对象必须含有个next方法,next方法返回一个拥有done(boolean)和value(一个具体的值或undefined)两个属性的对象。迭代结束done为true,否则为false

创建迭代器 

下面我们写一个创建数组迭代器的方法 

function createArrayIterator(arr) {let index = 0return {next() {if(index < arr.length) {return { done: false, value: arr[index++] }} else {return { done: true, value: undefined }}}}
}let nums = [1,2,3]
let names = ['小明', '小红', '小芳']let numsIterator = createArrayIterator(nums)
console.log(numsIterator.next()) // { done: false, value: 1 }
console.log(numsIterator.next()) // { done: false, value: 2 } 
console.log(numsIterator.next()) // { done: false, value: 3 } 
console.log(numsIterator.next()) // { done: true, value: undefined }
let namesIterator = createArrayIterator(names)
console.log(namesIterator.next()) // { done: false, value: '小明' } 
console.log(namesIterator.next()) // { done: false, value: '小红' }  
console.log(namesIterator.next()) // { done: false, value: '小芳' } 
console.log(namesIterator.next()) // { done: true, value: undefined }

将一个非可迭代对象 转化为 可迭代对象 

在这之前,我们可以提前考虑一下,为什么for of可以遍历数组而不能遍历对象,就是因为数组本身是有迭代器的,而对象则没有 

 

 

从上面两个示例应该就能明白了,对象中没有 iterable 迭代器,因为不可for of 遍历 

如果我们也想将一个非可迭代对象 转化为 可迭代对象 只需要在其中增加 Symbol.iterator 方法即可如下:

let info = {name: 'wft',age: 18,height: 1.88,// 增加 Symbol.iterator 方法 转为一个可迭代对象[Symbol.iterator]() {let values = Object.values(this)let index = 0let iterator = {next() {if(index < values.length) {return { done: false, value: values[index++] }} else {return { done: true, value: undefined }}}}return iterator}
}let infoIterator = info[Symbol.iterator]()
console.log(infoIterator.next()) // { done: false, value: 'wft' }
console.log(infoIterator.next()) // { done: false, value: 18 }
console.log(infoIterator.next()) // { done: false, value: 1.88 } 
console.log(infoIterator.next()) // { done: true, value: undefined }for(let item of info) {console.log(item)
}
//wft
//18
//1.88

注意:一定是 [Symbol.iterator] 规定好的,不可修改

arguements也是一个可迭代对象 

是不是迭代对象就看有没有迭代器即可 

function foo() {console.log(arguments)for(let item of arguments) {console.log(item)}
}foo(1,2,3)

生成器 

生成器函数:

  • function 后面会跟上符号 *
  • 代码的执行可以被yield控制(类似于断点)
  • 生成器函数默认在执行时,返回一个生成器对象(并不会执行函数内部的代码)
  •  要想执行函数内部的代码,需要生成器对象调用它的next方法操作
  • 当调用next,执行内部函数代码时,当遇到yield时,就会中断执行

调用生成器函数,将返回生成器对象,但是并不会执行函数内部的代码,生成器对象中也有个next方法,调用next方法才会去执行方法内部的代码,遇到yield将终止执行 。示例如下:

// 生成器函数
function * fn() {console.log(111)yieldconsole.log(222)yieldconsole.log(333)
}// 调用生成器函数,返回生成器对象
// 注意:并没有执行fn中的代码
const generator = fn()// 生成器也有一个 next 方法,调用next方法,将执行 fn 内部的代码,遇到 yield 将终止执行
generator.next() // 111
generator.next() // 222
generator.next() // 333

yield 叫产出,可以产出数据,也就是在 yield 后面跟上数据,那么它将会作为next方法的返回值,示例如下:

// 生成器函数
function * fn() {// 第一次调用next方法,会执行这的代码...yield '哈哈哈'// 第二次调用next方法,会执行这的代码...yield {name: 'wft', age: 18}// 第三次次调用next方法,会执行这的代码...
}const generator = fn()console.log(generator.next()) // { value: '哈哈哈', done: false }
console.log(generator.next()) // { value: { name: 'wft', age: 18 }, done: false }

我们调用next方法的时候,也是可以传递参数的,那么这个参数就作为yield的返回值返回,示例如下: 

// 生成器函数
function * fn() {let num1 = yield '哈哈哈'console.log(num1, 'num1') // 注意这里得调用第二次next方法的时候才会执行  ---  结果:123let num2 = yield {name: 'wft', age: 18}console.log(num2, 'num2') // 同样这里得调用第三次next方法的时候才会执行  ---  结果:456
}const generator = fn()console.log(generator.next()) // { value: '哈哈哈', done: false }
console.log(generator.next(123)) // { value: { name: 'wft', age: 18 }, done: false }
console.log(generator.next(456)) // { value: undefined, done: true }

使用生成器代替上面的迭代器 

function * createArrayGenerator(arr) {// 方式一:for(let i = 0; i < arr.length; i++) {yield arr[i]}// // 方式二:yield语法糖写法 等同于方式一// yield * arr
}let nums = [1,2,3]// nums生成器对象
let numsGenerator = createArrayGenerator(nums)console.log(numsGenerator.next()) // { value: 1, done: false }
console.log(numsGenerator.next()) // { value: 2, done: false }
console.log(numsGenerator.next()) // { value: 3, done: false }
console.log(numsGenerator.next()) // { value: undefined, done: true }

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...