Set 类似于数组,是一种集合的数据结构,但Set中所有的成员都是唯一的。
Set 本身是一个构造函数,用来生成 Set 数据结构
const s1 = new Set()
s1.add(1)
s1.add(2)
s1.add(1)
// s1 的值为 {1, 2}
Set 函数可以接受一个可循环的数据结构(如数组、类数组、含有 iterable 接口 的其他数据结构)作为参数来初始化:
const s2 = new Set([1,2,1,4,3,4])
// s2 的值为 {1, 2, 3, 4}
-
onst s2 = new Set(['a','b','c','d']) // s2 的值为 {"a", "b", "c", "d"} s2.size // 4
-
向 Set 中添加一个值,返回 Set 结构本身,所以可以使用链式调用
s2.add('e').add('f').add('g'); // s2 的值为 {"a", "b", "c", "d", "e", "f", "g"}
-
s2.delete('c') // 返回true,表示成功删除 // s2 的值为 {"a", "b", "d", "e", "f", "g"}
-
s2.has('d') // 返回true,表示存在"d" s2.has('y') // 返回false,表示不存在"y"
-
清除所有成员,无返回值
s2.clear() // Set(0) {}
- keys():返回键名
- values():返回键值
- entries():返回所有成员
- forEach():循环Set实例所有成员
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
//可以省略values方法,直接用for...of循环遍历Set。
for (let x of set) {
console.log(x);
}
// red
// green
// blue
let array = [1,2,1,4,5,3,'1'];
[...new Set(array)] // [1, 2, 4, 5, 3, "1"]
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));// set {2, 3}
// 差集
let difference = new Set([...a].filter(x => !b.has(x)));// Set {1}
WeakSet 结构与 Set 类似,也是不重复的值的集合。
但WeakSet 的成员只能是对象,而不能是其他类型的值
- WeakSet没有size属性
- 不能循环,因为内部数据随时可能消失,循环机制无法保证数据存在
- 使用的WeakSet的优势是使用完后被垃圾回收,减少内存资源浪费。
JavaScript的对象 Object 本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
为了解决这个问题,ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
const m1 = new Map()
const k = {a:3}
m1.set(k, 'mapValue') // { {a:3} => "mapValue"}, 对象也能档 key,真太便利啦
m1.get(k) // mapValue
Map 还可以接受一个数组作为参数,这个数组的成员是一个个表示键值对的数组
const m2 = new Map([
['name', '大彬哥'],
['age', 18]
])
// {'name'=>'大彬哥', 'age'=>18}
-
const m2 = new Map([ ['name', '大彬哥'], ['age', 18] ]) m2.size // 2
-
set设置一个键名为 key 键值为 value 的成员,并返回整个 Map 结构,如果已经存在该键名,则会更新键值
get读取这个 key 对应的值,如果没有则返回 undefined
m2.set('sex', 'boy') // {"name" => "大彬哥", "age" => 18, "sex" => "boy"} m2.set('name', '涂涂') // {"name" => "涂涂", "age" => 18, "sex" => "boy"} m2.get('sex') // "boy"
-
m2.has('age') // true m2.delete('age') // true , // m2 变成了 {"name" => "涂涂", "sex" => "boy"} m2.clear() // m2 变成了 Map(0) {}
Map实例的循环方式和Set类似,可以用 keys、values、entries、forEach 等方式循环成员
const m2 = new Map([
['name', '大彬哥'],
['age', 18]
])
for (let key of m2.keys()) {console.log(key)}
// name
// age
for (let value of m2. values()) {console.log(value)}
// 大彬哥
// 18
for (let item of m2. entries()) {console.log(item[0], item[1])}
// name 大彬哥
// age 18
// 这里的 item 是一个数组,其中第一个值为键名,第二个值为键值
m2.forEach((value, key) => console.log(key,value))
// name 大彬哥
// age 18
let m_1 = new Map([[1, 'name'], ['name', 'js']]);
[...m_1]; // 返回值为 [[1,"name"],["name","js"]]
let arr = [[1, 12], [1, 24], ['name', 'ji'], ['name', 'js']];
let arr2m = new Map(arr);
// 返回值为 Map(2) {1 => 24, "name" => "js"}
WeakMap结构与Map结构类似,也是用于生成键值对的集合。
不同之处在于,WeakMap 不会阻止它的键值被垃圾回收。那意味着你可以把数据和对象关联起来不用担心内存泄漏。
WeakMap 应用的典型场合就是 DOM 节点作为键名:
var vm = new WeakMap();
var element = document.querySelector('.element');
vm.set(element, "Original");
vm.get(element); // Original
element.parentNode.removeChild(element); // 删除节点,系统会回收element这个Dom节点对象
element = null;
vm.get(element); // undefined, WeakMap自动删除了element这个成员
在使用的过程中明显的Set和Map比我们之前经常使用的Array和Object是有明显的便捷优势的。
如果对数据结构存储的唯一性有要求,考虑使用Set。
如果数据的复杂程度高,考虑使用Map,在一些构建工具中是非常喜欢使用Map这种数据结构来进行配置,因为map是一种灵活、高效性、适合一对一查找的数据结构。
相比于 Map 与 Set 的强引用,弱引用可以令对象在 “适当” 情况下正确被垃圾回收,减少内存资源浪费。