Set 
一直以来,JS 只能使用数据和对象来保存多个数据,缺乏其他语言那样拥有丰富的集合类型。因此,在 ES6 新增了两种集合类型(Set 和 Map),用于在不同的场景中发挥作用。
Set 用于存放不重复的数据
1. 如何创建 set 集合 
javascript
// 创建了一个空的set集合
let mySet = new Set()javascript
// 创建了一个具有初始内容的set集合,内容来自于可迭代对象每一次迭代的结果
let mySet = new Set(iterable)2. 如何对 set 集合进行操作 
- add: 添加一个数据到 set 集合的末尾,如果数据已存在,则不进行任何操作。 
- set 使用
Object.is的方式判断数据是否相同。 - 特殊情况:针对+0 和-0 的情况,是相同的。
 
 - set 使用
 - has: 判断 set 中是否存在对应的数据
 - delete: 从 set 集合中删除对应的数据,如果数据不存在,则不进行任何操作。
 - clear: 清空 set 集合
 - size: 获取 set 集合的长度
 
3. 如何与数组进行相互转换 
javascript
const s = new Set([1, 2, 3, 4, 5])
// set 本身也是一个可迭代对象,每次迭代的结果就是每一项的值
const arr = [...s]去重
javascript
const arr = [22, 11, 33, 42, 21, 43, 55, 33]
const result = [...new Set(arr)]
console.log(result) // [22, 11, 33, 42, 21, 43, 55]
const str = 'aassqweerqqffoopp'
const s = new Set(str).join('')
console.log(s) // ['a', 's', 'q', 'w', 'e', 'r', 'o', 'p']4. 如果遍历 
4.1 for...of 遍历
4.2 set 方法携带的 forEach 方法遍历
注意:set 集合中不存在下标,因此 forEach 中的回调的第二个参数和第一个参数是一致的,均表示 set 中的每一项。
javascript
const s = new Set([1, 2, 3, 4, 5])
s.forEach((item, item2, s) => {
  console.log(item, item, s)
})5. 应用 
求两个数组的并集、交集、差集
javascript
const arr1 = [1, 3, 4, 5, 5, 9, 9]
const arr2 = [1, 2, 4, 5, 6, 7, 8]
// 并集
const union = new Set([...arr1, ...arr2])
console.log(union) // Set(9) {1, 2, 3, 4, 5, 6, 7, 8, 9}
// 交集
const intersection = new Set(arr1.filter((x) => arr2.includes(x)))
console.log(intersection) // Set(3) {1, 4, 5}
// 差集
const difference = [...new Set([...arr1, ...arr2])].filter(
  (x) =>
    (arr1.includes(x) && !arr2.includes(x)) ||
    (!arr1.includes(x) && arr2.includes(x))
)
console.log(difference) // Set(6) {3, 9}6. 手写 Set 
模拟 Set 的实现
javascript
class MySet {
  constructor(iterator) {
    // 验证是否是可迭代对象
    if (typeof iterator[Symbol.iterator] !== 'function') {
      throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`)
    }
    this._datas = []
    for (let item of iterator) {
      this.add(item)
    }
  }
  add(data) {
    if (!this.has(data)) {
      this._datas.push(data)
    }
  }
  has(data) {
    for (let 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(data, element)) {
        this._datas.splice(i, 1)
        return true
      }
    }
    return false
  }
  clear() {
    this._datas.length = 0
  }
  forEach(callback) {
    for (let item of this._datas) {
      callback(item, item, this)
    }
  }
  // 将该对象转变成可以迭代的对象
  *[Symbol.iterator]() {
    for (let item of this._datas) {
      yield item
    }
  }
  isEqual(data1, data2) {
    if (data1 === 0 && data2 === 0) {
      return true
    }
    return Object.is(data1, data2)
  }
}