Set
概念
- 类似于数组,成员唯一(内部元素没有重复的值)。
- Set 本身是一种构造函数,用来生成 Set数据结构。
- Set 对象允许你储存任何类型的唯一值,无论是原始值或者是对象引用。
Set实例对象的方法:
- add(value):添加某个值,返回 Set 结构本身(可以链式调用)。
- delete(value):删除某个值,删除成功返回true,否则返回false。
- has(value):返回一个布尔值,表示该值是否为Set的成员。
- clear():清除所有成员,没有返回值。
Set实例对象的属性:
- size:返回Set实例的成员总数
Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:
- +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复
- undefined 与 undefined 是恒等的,所以不重复
- NaN 与 NaN 是不恒等的,但是在 Set 中认为NaN与NaN相等,所有只能存在一个,不重复。
- {} {} 两个空对象的指针不一样,所以会重复
let a = undefined
let b = undefined
console.log(a==b,a===b)
let c = NaN
let d = NaN
console.log(c==d,c===d)
let e = {}
let f = {}
console.log(e==f,e===f)
let g = +0
let h = -0
console.log(g==h,g===h)
let arr = [undefined, undefined, NaN, NaN, {}, {}, -0, +0];
console.log(new Set(arr))
应用
数组去重
var array = [0,1,1,2,2,5,5,66,99,65,65];
console.log(Array.from(new Set(array))); //Array(7) [0, 1, 2, 5, 66, 99, 65]
console.log([...new Set(array)]); //Array(7) [0, 1, 2, 5, 66, 99, 65]
数组的并集
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let s1 = new Set([...arr1,...arr2]) //这样就把重复的3去掉了
console.log([...s1]);
数组的交集
let arr1 = [1,2,3,1];
let arr2 = [3,4,5,4];
let s1 = new Set(arr1);//先去除arr1数组自身的重复项
let s2 = new Set(arr2);//去除arr2数组自身的重复项
let arr = [...s1].filter((item)=>{
return s2.has(item) //has方法看s2里有没有item这一项
})
console.log(arr)
数组的差集
let arr1 = [1,2,3,1];
let arr2 = [3,4,5,4];
let s1 = new Set(arr1);
let s2 = new Set(arr2);
let arr = [...s1].filter((item)=>{
return !s2.has(item)
})
console.log(arr)
遍历Set
Array可以使用下标,Map和Set不能使用下标,ES6引入了iterable类型,Array,Map,Set都属于iterable类型(iterable内置forEach方法),它们可以使用for...of循环来遍历,意思为循环集合中的元素。
遍历方法
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回键值对的遍历器。
forEach():使用回调函数遍历每个成员。
由于Set结构没有键名,只有键值(**或者说键名和键值是同一个值**),所以keys方法和values方法的行为完全一致。
const set = new Set(['a', 'b', 'c'])
for (let item of set.keys()) {
console.log(item)
}
// a
// b
// c
for (let item of set.values()) {
console.log(item)
}
// a
// b
// c
for (let item of set.entries()) {
console.log(item)
}
// ["a", "a"]
// ["b", "b"]
// ["c", "c"]
// 直接遍历set实例,等同于遍历set实例的values方法
for (let i of set) {
console.log(i)
}
// a
// b
// c
set.forEach((value, key) => console.log(key + ' : ' + value))
// a: a
// b: b
// c: c
Map
概念
- Map类似于对象,是键值对的集合,但是“键”的范围不限制于字符串,各种类型的值(包含对象)都可以当作键,可用于做数据储存。
- 初始化
Map需要一个二维数组,或者直接初始化一个空Map。 - Map里面也不可以放重复的项。
Map对象的属性:
- size:返回Map对象中所包含的键值对个数
Map对象的方法:
- set(key, val): 向Map中添加新元素
- get(key): 通过键值查找特定的数值并返回
- has(key): 判断Map对象中是否有Key所对应的值,有返回true,否则返回false
- delete(key): 通过键值从Map中移除对应的数据
- clear(): 将这个Map中的所有元素删除
let map = new Map([['js','react']]);
map.set('js','react');//看看是否可以放重复的项
map.set('javaScript','vue');
console.log(map)
应用
遍历Map
遍历方法
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
const map = new Map([['a', 11], ['b', 22]])
for (let key of map.keys()) {
console.log(key)
}
// "a"
// "b"
for (let value of map.values()) {
console.log(value)
}
// 11
// 22
for (let item of map.entries()) {
console.log(item)
}
// ["a", 11]
// ["b", 22]
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value)
}
// "a" 11
// "b" 22
// for...of...遍历map等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value)
}
// "a" 11
// "b" 22
Map与obj转换
- Object.entries获取对象的键值对
- Object.FromEntries把键值对列表转成对象
- Object.entries和Object.fromEntries之间是可逆的。
Map转Obj
const obj = {}
const map = new Map(['a', 11], ['b', 22])
for(let [key,value] of map) {
obj[key] = value
}
console.log(obj)
// {a:11, b: 22}
let map=new Map([['foo','hello'],['bar',100]]);
let obj=Object.fromEntries(map);
console.log(obj);
Obj转Map
let obj={foo:'hello',bar:100};
let map=new Map(Object.entries(obj));
console.log(map)
// Map(2) {"foo" => "hello", "bar" => 100}
Array与Map转换
Array转Map
const arr = [{
id: 1,
goodNo: '1001'
}, {
id: 2,
goodNo: '1002'
}, {
id: 3,
goodNo: '1003'
}]
const map = new Map()
arr.forEach(item => {
map.set(item.id, item)
})
console.log(map)
Map转Array
var map = new Map();
map.set(1, "111");
map.set(2, "222");
map.set(3, "333");
console.log(map)
// map -> array
var arr = Array.from(map); // 二维数组
console.log(arr)
console.log(arr.flat()); // 压平(成为一维数组)
// (6) [1, "111", 2, "222", 3, "333"]
// 或:使用...rest运算符
console.log([...map]); // 把map中的entries扩展为数组元素。
Map与Object
1.key的数据类型范围不同
- Object:可以作为key的有:number,string,以及es6里面的symbol;
- Map:js目前存在的数据类型均可以作为key;
2.key的顺序
- Object: 如果对象的key中同时存在number string symbol 三种类型的时候,通过Object.keys得到的顺序是数字(升序) -> string(symbol)以创建的顺序;
- Map: key以声明的顺序进行排序;
3.创建方式不同
- Object:创建方式
- const obj1 = new Object()
- const obj2 = {}
- const obj3 = Object.create({})
- Map:创建方式:
- const map = new Map();
4.key的调用方式不同
- 通过key取值:
- Object:可通过 . 或 []
- Map:只能用原生的get方法进行调用;
- 判断是否有某个属性
- Object:'a' in obj;判断obj中是否有a这个属性;
- Map:map.has('a');判断map中是否有a这个属性;
5.设置属性的方式不同
- Object:
- obj.a = 1;
- obj['a'] = 1;
- Map:js目前存在的数据类型均可以作为key;
- map.set('a',1)
6.删除key的方式
- Object: 自身没有删除属性的方法;一般删除对象属性的方式: delete obj.a
- Map: map.delete('a') ----删除a属性; map.clear() ----删除所有的属性;
7.获取size
- Object: 通过Object.keys(obj) 返回一个数组,通过获取数组的长度来获取size;
- Map: 自身带有size属性;map.size,size属性无法修改;
8.Iterating(迭代)
- Object: 不可以
- Map: 可以;
如何判断一个数据是否可以迭代的方式
- typeof [][Symbol.iterator] //function
- typeof new Map()[Symbol.iterator] //function
- typeof {}[Symbol.iterator] //undefined
- typeof 1[Symbol.iterator] //undefined
9.JSON操作
- Object: 支持JSON.stringify和JSON.parse的操作;
- Map: 不支持;
10.this不同
const f = function(){ console.log(this) }
Object:
const obj = {fn:f}
Map:
const map = new Map()
map.set('fn',f)
obj.fn() //指向obj
map.get('fn')() //取决于函数的调用者;