本文最后更新于:2024-11-02T17:08:04+08:00
目录
前言
概念
优点
用法
对象迭代能力
为什么对象没有迭代器
迭代器的实现
生成器
基础语法
生成器传参
生成器委托
可终止迭代器
总结
前言
在ES6中引入了迭代器的概念,它是一种遍历数据集合的机制,提供了一种简单而一致的方式来访问集合中的每个元素,在集合与映射这篇文章中,我们就已经初步认识了Symbol.iterator这个概念。
概念
迭代器是通过迭代协议实现的,每一个拥有该协议的对象都可以称作是可迭代的对象,这个协议的标识就是Symbol.iterator,它是ES6中引入的一个新的Symbol值,表示一个对象是否有可迭代性。可迭代对象的Symbol.iterator属性是一个函数,我们称为迭代器对象,运行这个函数会返回一个next函数(next函数可以当成是JS的原型链或者C中链表的指针),运行next函数后又可以接收两个属性:value和done;value表示当前迭代的值;done表示遍历完全部迭代。
在JS中可迭代的对象有以下几种:
- Array(数组)
- Map(映射)
- Set(集合)
- String(字符串)
- TypedArray(类数组)
- NodeLists(Dom节点)
需要注意的是Object没有迭代能力
优点
灵活性:迭代器提供了一套灵活的遍历机制,使用相同的语法和操作方式于不同类型的数据结构
可迭代性:通过实现迭代器协议,可以让对象具有可迭代性,从而可以使用for of循环来遍历对象,增强代码可读性
惰性求值:迭代器是一种惰性求值的机制,只有在需要下一个元素时才会取值,这样可以节省内存,提高性能
可中断性:迭代器可以在任意时刻中断遍历,而不需要遍历整个数据结构,提高代码的效率
支持函数式编程:迭代器是函数式编程中常用的工具,它可以和其他函数式编程的特性一起使用,例如高阶函数、map、filter、reduce 等等
用法
简单介绍一下迭代器的用法,使用[Symbol.iterator]()运行迭代对象,获取next,运行next获取迭代值
我们可以借助while对数组执行遍历操作
或者通过ES6新增的for of对迭代对象进行遍历,for of和for in类似,for in是遍历索引,for of是遍历属性值
对象迭代能力
为什么对象没有迭代器
对象是一种无序的集合类型,与数组或类数组不同,它的属性名称是字符串或Symbol类型,并且不具备索引。因此对象不能像数组一样使用简单的循环结构来遍历属性值,而是需要通过一些特殊的方法来实现对象的迭代。
迭代器的实现
基于上面的用法,我们可以尝试在对象上实现迭代器
可以看到,对象像迭代对象一样也可以通过迭代的方式获取到值
生成器
生成器(Generator)是 ES6 中新增的一种特殊函数,它的语法与迭代器有共同之处,可以看作是一种特殊的迭代器,它通过function*关键字来定义。生成器函数的内部可以使用yield关键字来暂停函数的执行,并返回执行结果,同时也可以再次从暂停的位置开始执行。在函数外部使用next()函数来获取生成器的迭代值,结构与上面的迭代器相同,包含value和done值
基础语法
比如,我们使用一个数组来表示函数异步的内容,在内部使用yield对函数进行暂停操作,在外部使用generator.next()对内部暂停的结果取迭代值
生成器传参
在next函数中传入参数可以将参数带入生成器函数中,比如
生成器委托
生成器之间可以使用yield*关键字进行传递,函数中的多个生成器会连接在一起,一起输出值
上面的getInfo等同于
可终止迭代器
可终止迭代器在ES6中并未正式加入,但是却有相关的声明,使用return函数可以跳出迭代。使用throw函数可以跳出迭代并抛错,所以我们可以借助上面的对象迭代器的方式,实现一个迭代终止的功能
首先我们实现一个数组的迭代器,数组和对象区别在于已经存在length属性,所以我们做个兼容就行了
然后我们在迭代器中增加return函数和throw函数
接着在数组中使用一下
return函数:
throw函数:
总结
本文介绍了JS迭代器的概念以及用法,并使用反射机制在Object中实现了迭代器,此外,生成器是特殊的迭代器,它的使用与迭代器类似,最后实现了迭代器中的可终止迭代器,使迭代器拥有终断功能
以上就是全部内容了,感谢你的阅读,如果觉得文章不错的话,还望支持一下博主,谢谢~