Set和Map
Set和Map是ES6新增加的数据类型。其中Set被称作"集合",Map被称作"映射"。
新增的这两个数据结构提供了更灵活和强大的方式来处理和存储数据。
Set
Set是一个简单值的集合,类似于数组。Set的特点:Set成员的值都是唯一的,不允许重复。
通过Set这一特性,可以运用Set进行去重操作。
-
数组去重:
javascriptconst arr = [1, 2, 3, 1, 2, 3, 1, 1] const newArr = [...new Set(arr)] console.log(newArr);
结果为:
通过数组的解构和Set无重复值的特性,可以产生一个数组去重的小妙招。
-
字符串去重:
javascriptconst str = 'abcabcaaa' const newStr = [...new Set(str)].join('') console.log(newStr);
结果为:
数组可以通过Set特性去重,而且数组还有join方法可以将数组转换成字符串,这样我们可以联想到字符串去重的方法。
Set常用方法
-
通过
new Set()
初始化Set对象:javascriptconst set = new Set() //或从一个数组创建 const arr = [1,2,3,4] const set = new Set(arr)
-
调用
add(value)
方法向 S集合 中添加指定元素:javascriptset.add(1)
-
调用
has(value)
方法检查集合中是否存在指定元素:javascriptset.has(2)
-
调用
delete(value)
方法删除集合中的指定元素:javascriptset.delete(1)
-
调用
clear()
方法清空集合内所有元素:javascriptset.clear()
-
set对象中的
size
属性可以返回集合中元素的数量:javascriptset.add(1) set.add(1) console.log(set.size)//1(不存在重复值)
Set的遍历方法
- 调用
keys()
方法返回一个新的迭代器对象,该对象包含Set对象的每个元素的键。 - 调用
values()
方法返回一个新的迭代器对象,该对象包含Set对象的每个元素的值。 - 调用
entries()
方法返回一个新的迭代器对象,该对象包含Set对象的每个元素(值和键)。
javascript
const set = new Set([1, 2, 3, 1, 2, 3, 4])
console.log(set.keys());
console.log(set.values());
console.log(set.entries());
结果为:
遍历Set的方法
-
forEach
方法:和数组一样,Set也有forEach方法。
javascriptconst set = new Set([1, 2, 3, 1, 2, 3, 4]) set.forEach((item) => { console.log(item) })
结果为:
-
for...of
循环:javascriptconst set = new Set([1, 2, 3, 1, 2, 3, 4]) for (let item of set) { console.log(item) }
结果为:
Set的优缺点
- 优点:
- Set中的元素都是唯一的,不会重复的值。
- 因为Set中的值是唯一的,所有查找、删除和添加的操作执行得更快。
- 缺点:
- 在ES6中,Set保持了插入顺序,但是存在兼容问题。
- 与数组不同,Set不能通过索引来访问Set中的元素。
Map
在普通对象中,对象的键名的类型都是字符串,如果不是字符串类型也会被转换为字符串类型。eg:
javascript
let n = 123
const obj = {
[n]: 1,
n: 1,
name: '张三',
[[]]: '1'
}
console.log(obj);
结果为:
都转换成了字符串类型。
然而随着需求的不断增加,出现了对象中的键名需要是其他类型的需求。因此JavaScript提供了Map这一数据结构。
Map这一数据结构允许使用任何值作为键。
注意:不要将数组的map方法和Map数据结构记混。
Map常用方法
-
通过
new Map()
初始化Map对象:javascriptconst map= new Map()
-
调用
set(key,value)
方法向Map中添加一个键值对:javascriptmap.set('name','张三')
注意:不要和上面的Set数据结构搞混喽。
-
调用
get(key)
方法根据提供的键名返回对应的值,如果不存在该键名则返回undefined:javascriptmap.get('name')
-
调用
has(key)
方法可以检查是否包含指定的键:javascriptconsole.log(map.has('name'))
如果包含就返回true,如果不包含就返回false。
-
调用
delete(key)
方法可以删除指定的键值对:javascriptmap.delete('name')
-
调用
clear()
方法可以删除所有键值对:javascriptmap.clear()
-
Map的属性
size
可以返回键值对数量。
Map的遍历方法
与Set的遍历方法相似。
keys()
:返回一个新的迭代器对象,其中包含Map的所有键名。values()
:返回一个新的迭代器对象,其中包含Map的所有键值。entries()
:返回一个新的迭代器对象,其中包含Map的所有键值对。
javascript
const map = new Map();
map.set('1', '2')
map.set(['1'], '1')
console.log(map.keys());
console.log(map.values());
console.log(map.entries());
结果为:
遍历Map的方法
-
forEach
方法:javascriptconst map = new Map() map.set('name', '张三') map.set('age', 18) map.set('gender', '男') map.forEach((value, key) => { console.log(key, value) })
结果为:
-
for...of
循环:javascriptconst map = new Map() map.set('name', '张三') map.set('age', 18) map.set('gender', '男') for (let [key, value] of map) { console.log(key, value) }
结果为:
Map的优缺点
- 优点:
- Map可以存储如何类型的键和值。
- Map的键也是唯一的,不存在重复的键。
- Map内的顺序和插入顺序一致。
- 缺点:
- 存在兼容问题。
- Map不能和数组一样通过索引直接访问。
弱引用和强引用
WeakSet和WeakMap都是弱引用,首先了解一下什么是弱引用。
弱引用是不能确保其引用的对象不会被垃圾回收器回收的引用,而强引用是确保其引用的对象不会被垃圾回收器回收的引用。
也就是说,JavaScript引擎在执行代码时,对象通过变量直接赋值形成的引用会被视为强引用,垃圾回收器就不会回收这类对象;通过WeakMap
和WeakSet
建立的引用会被视为弱引用,这类引用无法阻止垃圾回收器的回收。
当一个变量被设置为null
时,会断开该变量与原对象间的引用,该对象就会变成垃圾回收器的回收目标。
eg:强引用
javascript
let person = { name: "张三" };
const person1 = [person];
person = null;
console.log(person1);
创建一个叫person
的对象,并将该对象存储到person1
中;然后将person
设置为null
,断开引用,但是因为变量person1
存在对person
对象的强引用,所以该对象不会被垃圾回收器给盯上。
eg:弱引用
javascript
let person1 = new WeakMap();
let person = { name: "张三" };
person1.set(person, "张三");
person = null;
// 等待垃圾回收后
console.log(person1);
创建一个weakMap
对象person1
和一个对象person
,并且将该对象作为键,键值为"张三"
添加到person1
中;然后将变量person
设置为null
,断开了变量与对象的引用,然而person1
对person
是弱引用,所以垃圾回收器可以回收person
对象。
WeakSet和WeakMap
WeakSet
WeakSet和Set非常相似,但是有一些不同之处:
- 成员类型:WeakSet的成员只能是Symbol值和对象,不能是其他的数据类型;Set的成员可以是任意数据类型。
- 引用类型:WeakSet是弱引用;Set是强引用。
- 方法和属性:WeakSet不支持迭代,所以没有
forEach
,values
,keys
,entries
方法,并且也没有size
属性;Set有forEach
,values
,keys
,entries
方法,也有size
属性。 - 作用:WeakSet可以实现自动清理回收;Set可以通过元素的唯一性用于实现去重工作。
WeakMap
WeakMap和Map也非常相似,但是也是有一些不同:
- 键的类型:WeakMap的键类型只能是对象和Symbol值;Map的键类型可以是任意数据类型。
- 引用类型:WeakMap是弱引用;Map是强引用。
- 方法和属性:WeakMap不支持迭代,所以没有
forEach
,values
,keys
,entries
方法,并且也没有size
属性;Map有forEach
,values
,keys
,entries
方法,也有size
属性。 - 作用:WeakMap也可以实现自动清理回收;Map提供需要高效键值对的操作。