迭代器的介绍
JavaScript 原有的表示“集合”的数据结构,主要是数组(Array
)和对象(Object
),ES6 又添加了Map
和Set
。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map
,Map
的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
遍历器(Iterator)它是一种借口,为各种不同的数据结构提供统一的访问机制。 任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator
属性,或者说,一个数据结构只要具有Symbol.iterator
属性,就可以认为是“可遍历的”
数组也是迭代对象,所以应该也有Symbol.iterator
这个属性,值为一个函数。
那么函数是怎么实现的呢?
Obj.prototype[Symbol.iterator] = function() {
var iterator = { next: next };
var current = this;
function next() {
if (current) {
var value = current.value;
current = current.next;
return { done: false, value: value };
}
return { done: true };
}
return iterator;
}
原生具备iterator接口的数据结构
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
Set数据结构的介绍
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set
本身是一个构造函数,用来生成 Set 数据结构。
Set的属性和方法
Set.prototype.size
:返回Set
实例的成员总数。Set.prototype.add(value)
:添加某个值,返回 Set 结构本身。Set.prototype.delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。Set.prototype.has(value)
:返回一个布尔值,表示该值是否为Set
的成员。Set.prototype.clear()
:清除所有成员,没有返回值。
遍历
Set.prototype.keys()
:返回键名的遍历器Set.prototype.values()
:返回键值的遍历器Set.prototype.entries()
:返回键值对的遍历器Set.prototype.forEach()
:使用回调函数遍历每个成员
Set构造函数的简单实现
class Set {
//传入可以迭代的对象
constructor(iterator = []) {
if(typeof iterator[Symbol.iterator] !== 'function') {
throw new Error('请传入迭代对象')
}
this._arr = []
for(let i of iterator) {
this.add(i)
}
}
//判断两个元素是否全等
isEqual(a, b) { //static在类的内部不能使用
if(a == 0 && b == 0) {
return true
}
return Object.is(a ,b)
}
has(item) {
for(let it of this._arr) {
if(this.isEqual(item, it)) {
return true
}
}
return false
}
add(item) {
if(!this.has(item)) {
this._arr.push(item)
}
return this //支持链式调用
}
get size() { //是只读属性, 所以只需要使用到getter属性
return this._arr.length
}
delete(item) {
this.arr.forEach((it, index) => {
if(this.isEqual(it, item)) {
this._arr.splice(index, 1)
}
})
return this
}
clear() {
this._arr = []
}
//由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),
//所以keys方法和values方法的行为完全一致。
keys() {
return Object.values(this._arr)
}
values() {
return Object.values(this._arr)
}
entries() {
return Object.entries(this._arr)
}
forEach(callback) {
for(const it of this._arr){
callback(it, it, this)
}
}
//支持迭代
[Symbol.iterator](){
for(const it of this._arr){
yield it;
}
}
}
新知识:
Object.is()
的使用- class构造函数中static方法不能在类中使用
总结
总的来说,收获还是很大,非常感谢博客大佬,让我增长了我的知识层面。菜鸡的我,只有努力的增加提升自己。如果有错误,请指教,虚心接受。
参考文献:
Set 和 Map 数据结构 - ECMAScript 6入门 (ruanyifeng.com)