作为ES6新增的数据结构,在平时的业务中我倒是没怎么使用过,但是在刷算法题中,Set和Map倒是经常登场。Set作为哈希表,Map作为对象plus,下面就来一起学习一下Set和Map的使用吧
实例属性
Set.prototype.size ,和数组的长度一样理解就行,不过是length换成了size
实例方法
Set.prototype.add() ,如果Set中没有该元素,则插入,且每次只能插入一个元素。注意,Set中每个元素只能插入一次,既同一个Set集合中不能存在相同的元素
Set.prototype.clear() : 清除Set集合中所有的元素
Set.prototype.delete() : 移除某个元素,并返回一个布尔值表示是否移除成功
返回一个新的迭代器对象,该对象包含 Set
对象中的代表每个元素的 [value, value]
数组 。这与 Map
对象类似,因此 Set
的每个条目的 key 和 value 都相同。
按照值插入的顺序为 Set
对象中的每个值调用一次 callbackFn
。如果提供了 thisArg
参数,它将被用作每次调用 callbackFn
时的 this
值。
Set.prototype.has() :返回一个布尔值,表示Set中是否存在该元素
Set.prototype.keys()和Set.protrtypr.values()返回是一个东西,即键值相同
除了forEach,for...of..也可以迭代
javascript
const mySet = new Set(['a','b','c','d'])
for (const [key,value] of mySet.entries()) {
console.log(`The key ${key} and the value ${value} is the same!`)
}
// The key a and the value a is the same!
// The key b and the value b is the same!
// The key c and the value c is the same!
// The key d and the value d is the same!
Set和Array的相互转换
csharp
let set = new Set([1,2,3,4]) //数组转Set
console.log(set) //{1,2,3,4}
let arr = [...set] //Set转数组法2
let arr2 = Array.from(set) //Set转数组法1
console.log(arr) //[1,2,3,4]
console.log(arr2) //[1,2,3,4]
javascript
let set = new Set([1,2,3,4])
// 求数组[2,3,4]和Set{1,2,3,4}的交集
const intersection = new Set([2,3,4].filter((item)=>set.has(item)))
console.log(intersection) //{2,3,4}
// 求数组[4,5,6]和Set{1,2,3,4}的差集
const difference = new Set([4,5,6].filter((item)=>!set.has(item)))
console.log(difference) //{5,6}
数组去重
ini
// 用于从数组中删除重复元素
const numbers = [2, 3, 4, 4, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 5, 32, 3, 4, 5];
console.log([...new Set(numbers)]);
// [2, 3, 4, 5, 6, 7, 32]
Set与字符串的关系
sql
const mySet = new Set('India')
console.log(mySet.size) //5
// 大小写敏感,且忽略重复项
new Set("Firefox"); // Set(7) { "F", "i", "r", "e", "f", "o", "x" }
new Set("firefox"); // Set(6) { "f", "i", "r", "e", "o", "x" }
这里附上MDN参考网站Set - JavaScript | MDN (mozilla.org)
javascript
let obj ={
'a':1,
'b':2,
c:3 //Object的键只能是字符或Symbol,它会自己转
}
const keys= Object.keys(obj)
console.log(keys)
const values= Object.values(obj)
console.log(values)
const arrs = Object.entries(obj)
console.table(arrs)
Map有个神奇的地方就是它可以复制,给我的感觉是和Object.assign一样,而且两者都是浅复制(拷贝),而Set是没有类似方法的
ini
const obj= {
a:0,
b:{c:1}
}
const target = {}
const obj2 = Object.assign(target,obj)
obj2.b.c = 0 //因为是浅拷贝,对.b的值同一个引用,所以obj.b.c也会变
console.log(obj2) //{a:0,b:{c:0}}
console.log(obj) //{a:0,b:{c:0}}
console.log(target===obj2) //true
这里提供一个深拷贝的方法
ini
const obj3 = { a: 0, b: { c: 0 } };
const obj4 = JSON.parse(JSON.stringify(obj3));
obj3.a = 4;
obj3.b.c = 4;
console.log(obj4); // { a: 0, b: { c: 0 } }
javascript
const myMap= new Map([['a','字母']])
console.log(myMap)
const myMap2 = new Map(myMap)
console.log(myMap2)
console.log(myMap===myMap2) //false
实例属性
这些属性在 Map.prototype
上定义,并由所有 Map
实例共享。
返回 Map
对象中的键值对数量。
实例方法
移除 Map
对象中所有的键值对。
移除 Map
对象中指定的键值对,如果键值对存在并成功被移除,返回 true
,否则返回 false
。调用 delete
后再调用 map.has(key)
将返回 false
。
以插入顺序为 Map
对象中的每个键值对调用一次 callbackFn
。如果为 forEach
提供了 thisArg
参数,则它将作为每一次 callback 的 this
值。
在 Map
对象中设置与指定的键 key
关联的值,并返回 Map
对象。
返回与指定的键 key
关联的值,若不存在关联的值,则返回 undefined
。
返回一个布尔值,用来表明 Map
对象中是否存在与指定的键 key
关联的值。
返回一个新的迭代器对象,其包含 Map
对象中所有元素的键,以插入顺序排列。
返回一个新的迭代对象,其中包含 Map
对象中所有的值,并以插入 Map
对象的顺序排列。
返回一个新的迭代器对象,其包含 Map
对象中所有键值对 [key, value]
二元数组,以插入顺序排列。
使用 for...of 迭代 Map
Map
可以使用 for...of
循环来实现迭代:
javascript
const myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (const [key, value] of myMap) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
for (const key of myMap.keys()) {
console.log(key);
}
// 0
// 1
for (const value of myMap.values()) {
console.log(value);
}
// zero
// one
for (const [key, value] of myMap.entries()) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
使用 forEach() 迭代 Map
Map
也可以通过 forEach()
方法迭代:
javascript
myMap.forEach((value, key) => {
console.log(`${key} = ${value}`);
});
// 0 = zero
// 1 = one
这里附赠个数组去重的的
数组里全是原始类型,直接用Set,但如果是引用类型那Set就失效了,这里看了某博主分享的后,自己也手写了一遍,注释比较全,嘿嘿!
javascript
function uniqueArr(arr) {
const res = []
for (let iterator of arr) {
let sameFlag = false
for (let item of res) {
if (equl(iterator, item)) { //有相等就退出
sameFlag = true
break
}
}
if (!sameFlag) res.push(iterator)
}
return res
}
function equl(obj1, obj2) {
if ((typeof obj1 === 'object' && obj1 !== null) && (typeof obj2 === 'object' && obj2 !== null)) {
// 都是非null的对象
if (Object.keys(obj1).length !== Object.keys(obj2).length) return false
for (const key in obj1) {
if (obj2.hasOwnProperty(key)) {
if (!equl(obj1[key], obj2[key])) {
// 属性值不相同,返回false
return false;
}
} else {
// 没有相同的key,直接返回false
return false;
}
}
// 能到这,就是属性数量、属性名、属性值都相同,那就可以判定这两个对象相同
return true;
} else {
// 原始类型作比较,最后的出口
return obj1 === obj2
}
}
let arr = [1, 1, '2', 3, 1, 2,
{ name: '张三', id: { n: 1 } },
{ name: '张三', id: { n: 1 } },
{ name: '张三', id: { n: 2 } }
]
console.log(uniqueArr(arr))