Map
Map类似一个高配版的Object
Map | Object | |
---|---|---|
默认情况下 | 默认情况下不包含任何键,所有键都是开发人员添加进去的 | Object原型链上有一些默认的键 |
键的类型 | 键可以是任意类型数据,就连函数都可以 | Object的键只能是String或Symbol |
键值对个数 | 通过size属性获取 | Object需要手动计算 |
性能 | Map在频繁增删键值对的场景下性能要比Object好 | Map在频繁增删键值对的场景下性能要比Object好 |
适用场景
- 要添加的键值名和Object上的默认键值名冲突,又不想改名时,可以换用Map。
- 需要String和Symbol以外的数据类型做键值时,用Map。
- 键值对很多,有需要计算数量时,用Map。
- 需要频繁增删键值对时,用Map。
使用
属性
map.size // 2
方法
let myMap1 = new Map();
myMap.set("key1", "value1");
myMap.set("key2", "value2");
let myMap2 = new Map([["key1", "value1"], ["key2", "value2"]]);
map.clear(); // 清空
map.delete('key2');
map.get('key1');
map.has('key1'); // 是否包含某键名对应的值
遍历
map.keys(); // 返回一个新的 Iterator对象, 它按插入顺序包含了Map对象中每个元素的键 。
map.values() // 返回键值的遍历器
map.entries() // 返回键值对的遍历器
map.forEach() // 使用回调函数遍历每个成员
const map = new Map([
['a', 1],
['b', 2],
])
for (let key of map.keys()) {
console.log(key)
}
// "a"
// "b"
for (let value of map.values()) {
console.log(value)
}
// 1
// 2
for (let item of map.entries()) {
console.log(item)
}
// ["a", 1]
// ["b", 2]
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value)
}
// "a" 1
// "b" 2
// for...of...遍历map等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value)
}
// "a" 1
// "b" 2
应用
// Map转为数组
Array.from(map);// [["key1", "value1"], ["key2", "value2"]]
[...map]; // [["key1", "value1"], ["key2", "value2"]]
// 数组转为Map
new Map(arr)
// Map转为对象
let obj = {}
for (let [k, v] of map) {
obj[k] = v
}
// 对象转为Map
for( let k of Object.keys(obj)){
map.set(k,obj[k])
}
// map合并数组
new Map([...new Map([[1, 'one'],[2, 'two'],[3, 'three']]), [2, 'dos']]);
// map合并map
new Map([...new Map([[1, 'one'],[2, 'two'],[3, 'three']]), ...new Map([[1, 'uno'],[2, 'dos']])]);// 合并两个Map对象时,如果有重复的键值,则后面的会覆盖前面的。
对比
Object 和 Map 的对比
Object
对象有原型, 也就是说他有默认的key
值在对象上面, 除非我们使用Object.create(null)
创建一个没有原型的对象;- 在
Object
对象中, 只能把String
和Symbol
作为key
值, 但是在Map
中,key
值可以是任何基本类型(String
,Number
,Boolean
,undefined
,NaN
….),或者对象(Map
,Set
,Object
,Function
,Symbol
,null
….); - 通过
Map
中的size
属性, 可以很方便地获取到Map
长度, 要获取Object
的长度, 你只能手动计算
weakMap 和 Map 的对比
- 只接受对象作为键名(
null
除外),不接受其他类型的值作为键名 - 键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的
- 不能遍历,方法有
get
、set
、has
、delete
Set
Sap类似一个高配版的Array,很多方面都像是加强的Map
-
所有元素的只有
key
没有value
,value
就是key
-
不允许出现键值重复
+0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复
undefined
与undefined
是恒等的,所以不重复NaN
与NaN
是不恒等的,但是在Set
中认为NaN
与NaN
相等,所有只能存在一个,不重复。 -
所有的元素都会被自动排序
-
不能通过迭代器来改变
set
的值,因为set
的值就是键
使用
属性
let s1 = new Set(); // Set(0) {}
// 传入数组,或类数组
let s2 = new Set([1, 2, 2, 3, 5]); // Set(4) {1, 2, 3, 5}
set.size; // 4
方法
set.add('b').add('a'); // Set(2) {"a", "b"}
set.clear(); // Set(0) { }
set.delete(1); // true,删除成功
set.delete(1); // false,值不存在无法删除
set.has(1); // true
set.has({}); // false 与对象内的"{}"并非同一个对象
// 间接使用数组的 map 和 filter 方法
new Set([...set].map((x) => x * 2)) // {2, 4, 6}
new Set([...set].filter((x) => x % 2 == 0)) // {2, 4}
遍历
set.values(); // SetIterator {1, 2, 3, 5}
set.keys(); // SetIterator {1, 2, 3, 5}
set.entries(); // 返回键值对的遍历器。
set.forEach(); // 使用回调函数遍历每个成员
for (let item of set.keys()) {
console.log(item)
}
for (let item of set.values()) {
console.log(item)
}
for (let item of set.entries()) {
console.log(item)
}
应用
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let s1 = new Set(arr1); //先去除arr1数组自身的重复项
let s2 = new Set(arr2); //去除arr2数组自身的重复项
// 并集
new Set([...arr1,...arr2]) // {1, 2, 3, 4, 5}
// 交集
[...s1].filter((item)=>s2.has(item)); // [3]
// 差集
[...s1].filter((item)=>!s2.has(item)); //[1,2] 这是arr1差arr2的结果是[1,2],如果是arr2差arr1就是[4,5]
// 数组去重
[...new Set(array)];
Array.from(new Set(array));
// Set转为数组
Array.from(new Set([1, 2, 3, 4, 5]))
对比
Array 和 Set 对比
Array
的indexOf
方法比Set
的has
方法效率低下Set
不含有重复值(可以利用这个特性实现对一个数组的去重)Set
通过delete
方法删除某个值,而Array
只能通过splice
。两者的使用方便程度前者更优Array
的很多新方法map
、filter
、some
、every
等是Set
没有的(但是通过两者可以互相转换来使用)
WeakSet 和 Set 对比
WeakSet
没有size
属性- 成员都是弱引用,可以被垃圾回收机制回收,可以用来保存 DOM 节点,不容易造成内存泄漏。
WeakSet
不可迭代,因此不能被用在for-of
等循环中。- WeakSet只能存储对象,而Set可以存储任意数据类型
WeakSet的弱引用特性导致它的方法只有以下3个:
add(value)
在末尾添加元素delete(value)
删除与这个值相等的元素has(value)
返回是否包含这个值
Map和Set区别
- 初始化需要的值不一样,Map需要的是一个二维数组,而Set 需要的是一维数组
- Map 和 Set 都不允许键重复
- Map的键是不能修改,但是键对应的值是可以修改的;Set不能通过迭代器来改变Set的值,因为Set的值就是键。*
Map 和 Set 数据结构是ES6语法,最大优点就是运行时间少大大提高了性能。
总结
Map
- 是一种类似于字典的数据结构,本质上是键值对的集合
- 可以遍历,可以跟各种数据格式转换
- 操作方法有:
set
、get
、has
、delete
、clear
WeakMap
- 只接受对象作为键名(
null
除外),不接受其他类型的值作为键名 - 键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的
- 不能遍历,方法有
get
、set
、has
、delete
Set
- 是一种叫做集合的数据结构
- 成员唯一、无序且不重复
[value, value]
,键值与键名是一致的(或者说只有键值,没有键名)- 允许储存任何类型的唯一值,无论是原始值或者是对象引用
- 可以遍历,方法有:
add
、delete
、has
、clear
WeakSet
- 成员都是对象
- 成员都是弱引用,可以被垃圾回收机制回收,可以用来保存
DOM
节点,不容易造成内存泄漏 - 不能遍历,方法有
add
、delete
、has
最后一句
学习心得!若有不正,还望斧正。希望掘友们不要吝啬对我的建议。