ES6之手写set
class MySet {
//如果没有默认值,传入一个空数组
constructor(iterater = []) {
//判断是不是一个可迭代对象,如果不是报错
if (typeof iterater[Symbol.iterator] !== 'function') {
throw new TypeError(`${iterater} is not iterable`);
}
this._datas = [];
//添加数据
for (const item of iterater) {
this.add(item);
}
}
get size() {
return this._datas.length;
}
add(item) {
//如果已经存在,就不再添加,进行去重
if (!this.has(item)) {
this._datas.push(item);
}
}
has(data) {
for (const item of this._datas) {
if(this.isEqual(data, item)){
return true;
}
}
return false;
}
delete(data){
//删除指定的数据
for(let i = 0; i < this._datas.length; i++){
const element = this._datas[i];
if(this.isEqual(element, data)){
this._datas.splice(i, 1);
return true;
}
}
return false;
}
clear(){
//清空数据
this._datas.length = 0;
}
//变为一个可迭代对象
*[Symbol.iterator]() {
for (const item of this._datas) {
yield item;
}
}
forEach(callback){
for (const item of this._datas) {
callback(item, item, this);
}
}
/**
* 判断两个是否相等
* @param {*} data1
* @param {*} data2
* @returns
*/
isEqual(data1, data2){
//先判断+0和-0,剩下的使用object.is
if(data1 === 0 && data2 === 0){
return true;
}else{
return Object.is(data1, data2);
}
}
}
这些代码只是仿造 set 集合,并不等同于真正的集合。因为原生的集合可以调用浏览器内部资源,效率更高。
如果没有传入内容,默认传入空数组。先判断是否是可迭代对象,然后找一个切入点,从 add 开始,循环添加。然后使用 has 判断是否有重复,使用 isEqual 判断是否相等,注意 +-0 的情况。删除也使用 isEqual 来判断相等,然后找到对应数据删除,clear 直接清空。
为了能够使用 for-of 循环,需要成为可迭代对象。创建一个 Symbol.iterator 属性,当外面调用 for-of 循环时,调用这个生成器函数返回生成器。不断取出 yield 当前值,赋值给外面的 item 。
forEach 将循环所有数据,依次调用回调函数,将三个参数放入回调函数中。
size 是访问器属性,只可以读取,不能进行赋值。表示集合内元素的数量。