Map
Map类型是一个存储着许多键值对的有序列表,其中的键名和对应的值支持所有的数据类型。
new Map()
—— 创建 map。map.set(key, value)
—— 根据键存储值。map.get(key)
—— 根据键来返回值,如果map
中不存在对应的key
,则返回undefined
。map.has(key)
—— 如果key
存在则返回true
,否则返回false
。map.delete(key)
—— 删除指定键的值。map.clear()
—— 清空 map。map.size
—— 返回当前元素个数。
如果想要在map里使用循环,可以:
map.keys()
—— 遍历并返回一个包含所有键的可迭代对象,map.values()
—— 遍历并返回一个包含所有值的可迭代对象,map.entries()
—— 遍历并返回一个包含所有实体[key, value]
的可迭代对象,for..of
在默认情况下使用的就是这个。
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// 遍历所有的键(vegetables)
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
// 遍历所有的值(amounts)
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
// 遍历所有的实体 [key, value]
for (let entry of recipeMap) { // 与 recipeMap.entries() 相同
alert(entry); // cucumber,500 (and so on)
}
const m = new Map()
//键名和对应的值都可以是任何数据类型,但是当键名是引用类型时,而且需要操作这个属性时
// m.set({lyc:'大帅比'},[1,2,3])
//需要把上面改成
const obj = { lyc: '大帅比' }
m.set(obj, [1, 2, 3])
//通过obj去操作
console.log(m.get(obj));
//判断map集合是否有obj属性
console.log(m.has(obj));
//删除
m.delete(obj)
Map和Object共同点:键值对的动态集合,支持增加和删除键值对
Object
//定义
const obj = { a:1,b:2 }
//添加键值对
obj.c = 3
//删除键值对
delete obj.c
Map
//定义
const map = new Map()
//添加键值对
map.set('a',1)
map.set('b',2)
//删除键值对
map.delete('a')
Map和Object不同点
1、构造方式
Map
const m = new Map()
//或者传入一个数组来初始化Map集合,这个数组中的每个元素都是子数组,子数组中包含键值对。
const m1 = new Map([['name','帅比'],['age',20]])
Object
//对象字面量
const obj = {
'a':'1',
'b':'2'
}
//构造函数
const obj = new Object()
2、键的类型
Object: 键类型必须是String或者Symbol,如果非String类型,会自动转为String类型。
Map: 键类型可以是任意类型,不会进行类型转换。在添加键值对时,会通过严格相等(===)来判断键属性是否已存在。但也有特例,NaN !==NaN,但是当作为Map的键名时是相等的key值。0和-0作为键名也是一样的。
3、键的顺序
Object: key是无序的,不会按照添加的顺序返回。
- 对于大于等于0的整数,会按照大小进行排序,对于小数和负数会当作字符串处理。
- 对于String类型,按照定义的顺序进行输出。
- 对于Symbol类型,会直接过滤掉,不会进行输出,想要输出Symbol类型属性,通过Object.getOwnPropertySymbols()方法
Map: key是有序的,按照插入的顺序进行返回。
4、键值对size
Object: 只能通过手动计算,通过Object.keys()方法或者通过for...in循环统计
const obj = {
2:2,
'1':1,
'b':'b'
}
Object.keys(obj).length; //3
Map: 直接通过size属性访问
const m = new Map()
m.size; //0
5、键值对的访问
Object
//1、添加或者修改属性,通过点或者中括号的形式
const obj = {}
obj.name = '帅比'
obj[Symbol('你好')] = '小帅比'
//2、判断属性是否存在
obj.name === undefined
obj.['name'] === undefined
//3、删除属性,通过delete关键字
delete obj.name
Map
//1、添加和修改key-value
const m = new Map()
m.set('name','帅比')
m.set(Symbol('你好'),'小帅比')
//2、判断属性是否存在
m.has('name') //true
m.has('age') //false
//取值
m.get('name') //帅比
//删除键值对
m.detele('name')
//获取所有属性名
m.keys()
//获取所有属性值
m.value()
//获取所有键值对
m.entries()
6、迭代器
Object本身不具有Iterator特性,默认情况下不能使用for...of进行遍历,只能只用for...in或者Object.keys()进行枚举对象中的非符号键属性。
Map支持迭代协议
const m = new Map([['name', '帅比'], ['age', 20]])
for(let [key,value] of m){
console.log(key,value); //name 帅比 age 20
}
7、JSON序列化
Object类型可以通过JSON.stringify()进行序列化操作
const obj = {
name:'帅比',
age:20
}
JSON.stringify(obj) //{"name":"帅比","age":20}
Map不能直接进行JSON序列化,如果需要序列化,可以先把Map实例转为数组,再序列化。
const m3 = new Map([['name','帅比'],['age',20],['dizhi','茂名']])
let aaa = JSON.stringify(Array.from(m3))
console.log(aaa); //[["name","帅比"],["age",20],["dizhi","茂名"]]
8、应用场景
Object
- 仅做数据存储,并且属性仅为字符串或者Symbol
- 需要进行序列化转换为JSON传输时
- 当作一个对象的实例,需要保留自己的属性和方法时
Map
- 会频繁更新和删除键值对时
- 存储大量数据时,尤其是key类型未知的情况下
- 需要频繁进行迭代处理
Set
Set 是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值只能出现一次。
它的主要方法如下:
new Set()
—— 创建一个set
set.add(value)
—— 添加一个值,返回 set 本身set.delete(value)
—— 删除值,如果value
在这个方法调用的时候存在则返回true
,否则返回false
。set.has(value)
—— 如果value
在 set 中,返回true
,否则返回false
。set.clear()
—— 清空 set。set.size
—— 返回元素个数。
Map
中用于迭代的方法在 Set
中也同样支持:
set.keys()
—— 遍历并返回一个包含所有值的可迭代对象,
Set只有值,所以下两个方法都是为了兼容Map
set.values()
—— 与set.keys()
作用相同,这是为了兼容Map
,set.entries()
—— 遍历并返回一个包含所有的实体[value, value]
的可迭代对象,它的存在也是为了兼容Map
。