,

WeakMap和WeakSet

Map 和 Object 的区别 关于 Map 和 Object 的区别,可以参阅下表: WeakMap We…

MapObject 的区别

关于 MapObject 的区别,可以参阅下表:

WeakMap

WeakMap 起源于 Map,因此它们彼此非常相似。但是,WeakMap 具有很大的不同。

WeakMap 的名字是怎么来的呢?

嗯,是因为它与它的引用链接所指向的数据对象的连接或关系没有 Map 的连接或关系那么强,所以它是弱的。

差异 1key 必须是对象

可以将任何值作为键传入 Map 对象,但 WeakMap 不同,它只接受一个对象作为键,否则,它将返回一个错误。

const John = { name: 'John' };
const weakMap = new WeakMap();
weakMap.set(John, 'student');
// WeakMap {{...} => "student"}
weakMap.set('john', 'student');
// Uncaught TypeError: Invalid value used as weak map key

差异 2:并非 Map 中的所有方法都支持

WeakMap 可以使用的方法如下:

  • delete
  • get
  • has
  • set

还有一个最大的不同是 WeakMap 不支持迭代对象的方法

差异 3:当 GC 清理引用时,数据会被删除

这是和 Map 相比最大的不同。

例如:

let John = { major: "math" };

const map = new Map();
const weakMap = new WeakMap();

map.set(John, 'John');
weakMap.set(John, 'John');

John = null;
/* John 被垃圾收集 */

John 对象被垃圾回收时,Map 对象将保持引用链接,而 WeakMap 对象将丢失链接。

所以当你使用 WeakMap 时,你应该考虑这个特点。

Set

Set 也非常类似于 Map,但是 Set 对于单个值更有用。

添加属性

使用 add 方法可以添加属性。

const set = new Set();

set.add(1);
set.add('john');
set.add(BigInt(10));
// Set(4) {1, "john", 10n}

Map 一样,Set 也不允许添加相同的值。

对于原始数据类型(boolean、number、string、null、undefined),如果储存相同值则只保存一个,对于引用类型,引用地址完全相同则只会存一个。

  • +0-0 在存储判断唯一性的时候是恒等的,所以不可以重复。
  • undefinedundefined 是恒等的,所以不可以重复。
  • NaNNaN 是不恒等的,但是在 Set 中只能存一个不能重复。

应用场景

接下来来看一下 Set 常见的应用场景:

//数组去重
...new Set([1,1,2,2,3])

//并集
var arr1 = [1, 2, 3]
var arr2 = [2, 3, 4]
var newArr = [...new Set([...arr1, ...arr2])]
//交集
var arr1 = [1, 2, 3]
var arr2 = [2, 3, 4]
var set1 = new Set(arr1)
var set2 = new Set(arr2)
var newArr = []
set1.forEach(item => {
   set2.has(item) ? newArr.push(item) : ''
})
console.log(newArr)
//差集
var arr1 = [1, 2, 3]
var arr2 = [2, 3, 4]
var set1 = new Set(arr1)
var set2 = new Set(arr2)
var newArr = []
set1.forEach(item => {
   set2.has(item) ? '' : newArr.push(item)
})
set2.forEach(item => {
   set1.has(item) ? '' : newArr.push(item)
})
console.log(newArr)

WeakSet

WeakSetSet 区别如下:

  • WeakSet 只能储存对象引用,不能存放值,而 Set 对象都可以
  • WeakSet 对象中储存的对象值都是被弱引用的,即垃圾回收机制不考虑 WeakSet 对该对象的引用,如果没有其他的变量或者属性引用这个对象值,则这个对象将会被垃圾回收掉。(不考虑该对象还存在与 WeakSet 中),所以 WeakSet 对象里有多少个成员元素,取决于垃圾回收机制有没有运行,运行前后成员个数可能不一致,遍历结束之后,有的成员可能取不到,被垃圾回收了。因此 ES6 规定,WeakSet 对象是无法被遍历的,也没有办法拿到它包含的所有元素。

WeakSet 能够使用的方法如下:

  • add(value) 方法:在 WeakSet 中添加一个元素。如果添加的元素已存在,则不会进行操作。
  • delete(value) 方法:删除元素 value
  • has(value) 方法:判断 WeakSet 对象中是否包含 value
  • clear( ) 方法:清空所有元素

下面来看一下 WeakSet 的代码示例,与 WeakMap 一样,WeakSet 也将丢失对内部数据的访问链接(如果内部数据已被垃圾收集)。

let John = { major: "math" };

const set = new Set();
const weakSet = new WeakSet();

set.add(John);
// Set {{...}}
weakSet.add(John);
// WeakSet {{...}}

John = null;
/* John 被垃圾收集 */

一旦对象 John 被垃圾回收,WeakSet 就无法访问其引用 John 的数据。而且 WeakSet 不支持 for-offorEach,因为它不可迭代。

比较总结

  • Map
    • 键名唯一不可重复
    • 类似于集合,键值对的集合,任何值都可以作为一个键或者一个值
    • 可以遍历,可以转换各种数据格式,方法 get、set、has、delete
  • WeakMap
    • 只接受对象为键名,不接受其他类型的值作为键名,键值可以是任意
    • 键名是对象引用,键名所指向的对象,会被垃圾回收机制回收
    • 不能遍历,方法 get、set、has、delete
  • Set
    • 成员唯一,无序且不会重复
    • 类似于数组集合,键值和键名是一致的(只有键值。没有键名)
    • 可以遍历,方法有 add、delete、has
  • WeakSet
    • 只能存储对应引用,不能存放值
    • 成员都是弱引用,会被垃圾回收机制回收
    • 不能遍历,方法有 add、delete、has

Previous Post

Next Post

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor