// 底层实现set, 手写实现set, 为了更加深刻的理解set集合 class MySet { // 此处定义一个数组来模拟set, 原生的set是用c或者c++ 可以操作浏览器底层的设计 _datas = Symbol("内部维护一个数组来模拟set") // 这里用户可以传入参数,也可以不传递参数 constructor(iterator = []) { if (typeof iterator[Symbol.iterator] !== "function") { // 判断传入的参数是否是一个可迭代的对象, 因为可迭代对象里面一定有一个知名符号的函数 return new Error(`你传入的${iterator}不是以恶可迭代对象`); } this._datas = []; // 传入的是一个迭代对象,那么进行遍历,放入MySet 的数组里面 for (const item of iterator) { // 添加到数组里面 this.add(item); } } /** * @description: 往set 里面添加一个数据 * @param : 添加的数据 * @return: {boolean} 结果 */ add(data) { // 添加一个数据,要判断set里面是否已经存在该数据了 if (!this.has(data)) { this._datas.push(data); return this._datas; } return this._datas; } /** * @description: 判断set集合内部里面是否存在某个元素 * @param : data 数据 * @return: {boolean} 结果 */ has(data) { for (const item of this._datas) { if (this.isEqual(data, item)) { return true; } } return false; } /** * @description: 判断两个数据是否相同 * @param : data1 数据1 * @param : data2 数据2 * @return: {boolean} */ isEqual(data1, data2) { // 因为set 内部+0 和 -0 是经过特殊测合理的,所以此处这样老模拟 if (data1 === 0 && data2 === 0) { return true; } // 如果比较的两个值不是0,则使用Oject.is return Object.is(data1, data2) } /** * @description: 删除set里面的某个值 * @param : data * @return: boolean 结果 */ delete(data) { for (let i = 0; i < this._datas.length; i++) { const element = this._datas[i]; if (this.has(data)) { this._datas.splice(i, 1); return true; } else { return false; } } } /** * @description: 清空set */ clear() { this._datas.length = 0; return this._datas; } /** * @description: 因为set本身也是一个可迭代的对象,生成器来构建一个迭代对象, 使用方法: 直接调用该生成器方法,就可以创建一个可迭代的对象 */ *[Symbol.iterator]() { for (const item of this._datas) { yield item; } } /** * @description: 为了实现set 的forEach() 方法, 注意forEach() 第一二参数和第二个参数是一样的,因为set集合不存在下标 * @param : * @return: */ forEach(callback) { for (const item of this._datas) { callback(item, item, this._datas); } } // 获取size的长度 get size(){ return this._datas.length; } } // 使用方法,和set 的使用方法一样 const arr = [1, 2, 3, 4, 1, 2, 3, 4]; const ms = new MySet(arr); console.log(ms)