在日常开发中,set 和map 数据结构是用的最多的, 但是都是JS 帮我搞定的,拒绝做api工程师, 接下来就开撸。
基本介绍
ES6 提供了新的数据结构 Set。
它类似于数组,但是成员的值都是唯一的,没有重复的值。
使用场景
- 数组去重 […new Set(arr)]
- 数据的唯一性
初始化
Set 本身是一个构造函数, Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
属性和方法
操作方法有:
- add(value):添加某个值,返回 Set 结构本身。
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
- has(value):返回一个布尔值,表示该值是否为 Set 的成员。
- clear():清除所有成员,无返回值。
遍历方法:
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员,无返回值
属性:
size: 返回Set集合的个数
模拟实现第一版
第一版的模拟实现:
接下来我们开始测试一下:
查看结果:
符合预期?的。
模拟实现第二版
最麻烦的还是迭代器的实现,Keys, values, 这些方法其实都和Es6的的迭代器有关系。
迭代器
所谓迭代器,其实就是一个具有 next() 方法的对象,每次调用 next() 都会返回一个结果对象,该结果对象有两个属性,value 表示当前的值,done 表示遍历是否结束。
我们去模拟实现一下呀。
function createIterator(items) {
let i = 0;
return {
next: function() {
let done = i >= items.length;
let value = !done ? items[i++] : undefined;
return {
done,
value
};
}
};
}
// test 一下
const a = createIterator([1,2,3]);
console.log(a.next()) // { done: false, value: 1 }
console.log(a.next()) // { done: false, value: 2 }
console.log(a.next()) // { done: false, value: 3 }
console.log(a.next()) // { done: true, value: undefined }
复制代码
OK我们去模拟下keys 和 values
// 这里特别强调的就是, […set.keys()], 这种写法必须返回的对象 加上一个
Symbol.iterator
我们来测试一下我们写的内容:
let set = new mySet([1, 2, 3]);
let set2 = new Set([1, 2, 3]);
console.log([...set2.keys()], [...set2.values()],[...set2.entries()], '9999')
console.log([...set.keys()], [...set.values()],[...set.entires()], '88888' )
复制代码
直接看截图:
ok 好像是对的, 以为到这里就大工告成了, 肯定不是, 特殊情况考虑, 如果我传入的是一个数字呢, 这时候我的mySet 是不会报错的, set 接受的参数是可迭代的, 如果不可迭代,是直接会new Error的。
我们如何去判断当前参数是不是可迭代的呢? 判断当前对象有没有Symbol.iterator 并且 Symbol.iterator 是一个function 返回的一个迭代器。 同理我们的mySet 也要在原型上实现迭代器属性:
最终版
test 一下
let set3 = new mySet([2,3]);
let set4 = new mySet(set3);
console.log(set3, set4);
let set5 = new mySet(5);console.log(set5);
复制代码
查看结果:
到这里我们的set就写完成了, 如果上面有什么不对的欢迎指正。
总结
本篇例子源码在github上 点击这里 欢迎star, 谢谢大家。
参考:冴羽大佬的这篇文章 传送门