ES6-Set-Map

在 JavaScript 中,ES6 为解决频繁操作数据时查找、统计不便的问题,新增了 Set 和 Map 数据结构。Set 成员值唯一,可用于去重等操作;Map 提供“值—值”对应,比 Object 更完善。此外,还介绍了 WeakSet 和 WeakMap 的特点及使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ES6-Set-Map

在 JavaScript 里通常使用 Array 或 Object 来存储数据。但是在频繁操作数据的过程中查找或者统计并需要手动来实现,并不能简单的直接使用。 比如如何保证 Array 是去重的,如何统计 Object 的数据总数等,必须自己去手动实现类似的需求,不是很方便。 在 ES6 中为了解决上述痛点,新增了数据结构 Set 和 Map,它们分别对应传统数据结构的“集合”和“字典”。首先,我们先来学习下 Set 数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。

一:Set 基本语法

  • 1.生成set实例,可以为空
  let s = new Set([1,2])

注意:初始化的参数必须是可遍历的,可以是数组或者自定义遍历的数据结构。

  • 2.添加数据
  s.add('goodbye')
  s.add('hello')
  console.log(s)    //{1, 2, "hello", "goodbye"}
  s.add('hello').add('goodbye')
  console.log(s)    //{1, 2, "hello", "goodbye"}   

注意:Set 数据结构不允许数据重复,所以添加重复的数据是无效的

  • 3.删除数据,clear删除全部数据
  s.delete('hello')
  console.log(s)    //{1, 2, "goodbye"}     
  • 4.统计数据,Set 可以快速进行统计数据
  //4.1判断是否包含数据项,返回 true 或 false
  console.log(s.has(1)) 	//1
  //4.2计算数据项总数
  console.log(s.size)   //3
  • 5.数组去重
let a1 = [1,2,3,2,3,4,5]
let a = new Set(a1)
console.log(a) 	 //{1, 2, 3, 4, 5}
   
  • 6.合并去重
let b1 = [1,3,4]
let b2 = [3,4,5,7]
let b = new Set([...b1,...b2])
console.log(b)  	//{1, 3, 4, 5, 7}
console.log([...b]) 	//[1, 3, 4, 5, 7]
console.log(Array.from(b)) 	 //[1, 3, 4, 5, 7]
  • 7.交集
let s1 = new Set(b1)
let s2 = new Set(b2)
let result = new Set(b1.filter(item => s2.has(item)))
console.log(Array.from(result)) 	//[3, 4]
            
  • 8.差集
let b3 = new Set(b1.filter(item => !s2.has(item)))
           let b4 = new Set(b2.filter(item => !s1.has(item)))
           console.log(b3) 		//{1}
           console.log(b4) 		//{5, 7}
           console.log([...b3, ...b4])	 	//[1, 5, 7]

二:遍历方式

1.keys():返回键名的遍历器
2.values():返回键值的遍历器
3.entries():返回键值对的遍历器
4.forEach():使用回调函数遍历每个成员
5.for…of:可以直接遍历每个成员

let m = new Set([1,2,'haihai','tutu'])
  console.log(m.keys())     // SetIterator {1, 2, "haihai", "tutu"}
  console.log(m.values())   // SetIterator {1, 2, "haihai", "tutu"}
  console.log(m.entries())   // SetIterator {1 => 1, 2 => 2, "haihai" => "haihai", "tutu" => "tutu"}

  m.forEach(item => {
      console.log(item)     //1  2  haihai  tutu
  })        

  for (let item of m) {
      console.log(item)     //1  2  haihai  tutu
  }

  for (let item of m.keys()) {
      console.log(item)     //1  2  haihai  tutu
  }

  for (let item of m.values()) {
      console.log(item)     //1  2  haihai  tutu
  }

  for (let item of m.entries()) {
      console.log(item)
  }
  //[1,1]   [2,2]  ["haihai","haihai"]  ["tutu","tutu"]

  for (let item of m.entries()) {
      console.log(item[0], item[1])
  }
    // 1 1    2 2    haihai haihai    tutu tutu

三:WeakSet

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

  • 1.WeakSet 的成员只能是对象,而不能是其他类型的值。
const qq = new WeakSet()
qq.add(1)
console.log(qq)     //Uncaught TypeError: Invalid value used in weak set
qq.add(Symbol())
console.log(qq)     //Uncaught TypeError: Invalid value used in weak set

关于WeakSetd 方法,仅有如下
(1).WeakSet.prototype.add(value)
在该 WeakSet 对象中添加一个新元素value.
(2)WeakSet.prototype.clear()
清空该 WeakSet 对象中的所有元素.
(3)WeakSet.prototype.delete(value)
从该 WeakSet 对象中删除value 这个元素
(4)WeakSet.prototype.has(value)
返回一个布尔值, 表示给定的值value是否存在于这个 WeakSet中

  let qq = new WeakSet()
    const q1 = {
        name: 'hello'
    }
    const q2 = {
        age: 18
    }
    qq.add(q1)
    qq.add(q2)
    console.log(qq)     //{{...},{...}} 0:Object
    qq.delete(q1)
    console.log(qq)     //{{...},{...}} 0:Object
    console.log(qq.has(q2))     //true
  • 2.WeakSet 对象中存储的对象值都是被弱引用的, 如果没有其他的变量或属性引用这个对象值, 则这个对象值会被当成垃圾回收掉. 正因为这样, WeakSet 对象是无法被枚举的, 没有办法拿到它包含的所有元素。

推荐阅读:Set

四:Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

Map 基本语法

  • 1.实例化
 let map = new Map()

注意:Iterable 可以是一个数组或者其他 iterable 对象,其元素为键值对(两个元素的数组,例如: [[ 1, ‘one’ ], [ 2, ‘two’ ]])。 每个键值对都会添加到新的 Map。null 会被当做 undefined。

  • 2.添加数据
let map = new Map()
let keyObj = {}
let keyFunc = function() {}
let keyString = 'one string'

 // 添加键
map.set(keyString, "和键'one string'关联的值")
map.set(keyObj, '和键keyObj关联的值')
map.set(keyFunc, '和键keyFunc关联的值')
console.log(map)
//{"one string" => "和键'one string'关联的值", {…} => "和键keyObj关联的值", ƒ => "和键keyFunc关联的值"}
  • 3.删除数据,clear删除所有数据
 map.delete(keyObj)
    console.log(map)
    // {"one string" => "和键'one string'关联的值", ƒ => "和键keyFunc关联的值"}
  • 4.统计数据
// 4.1统计所有 key-value 的总数
console.log(map.size) 		//2
// 4.2判断是否有 key-value
console.log(map.has(keyObj)) 	// false
  • 5.查询数据
console.log(map.get(keyFunc)) // 和键keyFunc关联的值

五:遍历方式

1.keys() :返回一个新的 Iterator 对象。它包含按照顺序插入 Map 对象中每个元素的 key 值
2.values() :返回一个新的 Iterator 对象。它包含按顺序插入Map对象中每个元素的 value 值
3.entries() :返回一个新的包含 [key, value] 对的 Iterator ? 对象,返回的迭代器的迭代顺序与 Map 对象的插入顺序相同
4.forEach() :将会以插入顺序对 Map 对象中的每一个键值对执行一次参数中提供的回调函数
5.for…of :可以直接遍历每个成员

let map = new Map()
    let a1 = {}
    let a2 = function() {}
    let a3 = 'one string'
    map.set(a1, "和键a1关联的值")
    map.set(a2, '和键a2关联的值')
    map.set(a3, '和键a3关联的值')
    map.forEach((value, key) => console.log(value, key))
    //和键a1关联的值 {}       和键a2关联的值 ƒ () {}      和键a3关联的值 one string

    for (let [key, value] of map) {
        console.log(key, value)
    }
    //{} "和键a1关联的值"       ƒ () {} "和键a2关联的值"       one string 和键a3关联的值 


    for (let key of map.keys()) {
        console.log(key)
    }
    //{}        f () {}      one string

    for (let value of map.values()) {
        console.log(value)
    }
    //和键a1关联的值        和键a2关联的值      和键a3关联的值

    for (let [key, value] of map.entries()) {
        console.log(key, value)
    }
    //{} "和键a1关联的值"       ƒ () {} "和键a2关联的值"        one string 和键a3关联的值

注意:其实 Object 也是按键值对存储和读取的,那么他俩之间除了我们之前说的区别以外还有其他的吗?

  • 1.键的类型

一个Object的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值,包括函数、对象、基本类型。

  • 2.键的顺序

Map 中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map 对象是按插入的顺序返回键值。

  • 3.键值对的统计

你可以通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值对个数只能手动计算。

  • 4.键值对的遍历

Map 可直接进行迭代,而 Object 的迭代需要先获取它的键数组,然后再进行迭代。

  • 5.性能

Map 在涉及频繁增删键值对的场景下会有些性能优势。

六:WeakMap

1.WeakMap结构与Map结构类似,也是用于生成键值对的集合。

   // WeakMap 可以使用 set 方法添加成员
    const wm1 = new WeakMap()
    const key = {
        foo: 1
    }
    wm1.set(key, 2)
    console.log(wm1)    //WeakMap {{Object} => 2}

    // WeakMap 也可以接受一个数组,
    // 作为构造函数的参数
    const k1 = [1, 2, 3]
    const k2 = [4, 5, 6]
    const wm2 = new WeakMap([
        [k1, 'foo'],
        [k2, 'bar']
    ])
    console.log(wm2)    //WeakMap {Array(3) => "bar", Array(3) => "foo"}

2.WeakMap与Map的区别有两点。
(1).WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。

 const map = new WeakMap()
    map.set(1, 2)
    // TypeError: 1 is not an object!
    map.set(Symbol(), 2)
    // TypeError: Invalid value used as weak map key
    map.set(null, 2)
    // TypeError: Invalid value used as weak map key

(2).WeakMap的键名所指向的对象,不计入垃圾回收机制。
推荐阅读:Map

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值