Object是最常用的一种引用类型数据,可用于存储键值对的集合。
Map是键值对的集合,才会用Hash结构存储。(map是es6以后新增的)
共同点:
键值对的动态集合,支持增加和删除键值对
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');
不同点:
1、构造方式
//Object
//对象字面量
const obj ={
'a':'1',
'b':'2'
}
//构造方式
const o= new Object();
const o2=Object.create();
//Map
//构造方法
const m = new Map();
const m2= new Map([
['a','1'],
['b','2']
])
2、键的类型-Object
键类型必须是String 或者Symbol,如果是非String类型,会进行数据类型转换
const obj2={
a:1
}
const arr1=[1,2]
obj2[3]=55;
obj2['3']=33
obj2[arr1]='arr'
console.log(obj2)
console.log(obj2) //{ 1,2: "arr", 3: 33, a: 1 } 3 和'3'是同一个,所以55会被33覆盖
键的类型-Map
可以是任意类型,包括对象、数组、函数等。不会进行类型转换。1和‘1' 是不同的Key
在添加键值对时,会通过严格相等(===)来判断键属性是否已存在。
特例:NaN
3、键的顺序
Object
key是无序的,不会按照添加的顺序返回。
1、对于大于等于0的整数,会按照大小进行排序,对于小数和负数会当做字符串处理。
2、对于String类型,按照定义的顺序进行输出。
3、对于Symbol类型,会直接过滤掉,不会进行输出,如果想要输出Symbol类型属性,通过Object.getOwnPropertySymbols() 方法
const obj3={
2:2,
'1':1,
'b':'b',
1.1:1.1,
0:0,
'a':'a',
[Symbol('s1')]:'s2',
[Symbol('s2')]:'s1'
}
console.log(obj3)//{ 0: 0, 1: 1, 1.1: 1.1, 2: 2, a: "a", b: "b" }
console.log(Object.keys(obj3)) // ["0", "1", "2", "b", "1.1", "a"]
Map
key 是有序的,按照插入的顺序进行返回。Symbol类型不会过滤点
const map =new Map([
[2,2],
['a','a'],
['c','c'],
]);
for (let key of map.keys()){
console.log(key) //2 a,c
}
4、键值对
size-Object
只能手动计算,通过Object.keys()方法或通过 for..in 循环统计
const obj ={
2:22,
'a1':'a',
'bb':'bbb'
}
console.log(Object.keys(obj).length);//3
size-Map
直接通过size属性访问
const map =new Map([
[2,2],
['a','a'],
['c','c'],
]);
console.log(map.size);//3
5、键值对的访问
Object
1.添加或者修改属性,通过 . 或者 [] 的形式
const obj ={};
obj.name = 'zhangsan';
obj['age']=18
console.log(obj);//{ age: 18, name: "zhangsan" }
2、删除属性
delete obj.name //或 delete obj['name']
//检测key 是否存在
obj.hasOwnProperty(key)
//访问键值对个数
const size = Object.keys(obj).length
Map
1.添加和修改key-value
const map = new Map();
map.set('name','zhangsan')
2.判断属性是否存在
map.has('name');
3.取值
//取值
map.get('name')
//删除键值对
map.delete('name')
//获取所有的属性名
map.keys()
// 清空map
map.clear()
6、迭代器
Object 本身是不具有Iterator特性,默认情况下不能使用 for..of 进行遍历
迭代Object 需要以某种方式获取他的键然后才能迭代
使用Object.entries()获取键值对
const obj ={};
obj.name = 'zhangsan';
obj['age']=18
for(let [key,value] of Object.entries(obj)){
console.log(key) // 'name','age'
}
// Object.entries(obj).forEach(([key,value])=>{
// console.log(key)
// })
// Object.entries(obj)
Map 结果的keys(),values(),entries()方法返回值具有Iterator 特性,可以直接使用 for..of
const map =new Map([
['name','zhangsan'],
['age',18]
]);
for(let [key,value] of map){
console.log(key,value) //"zhangsan","name","age",18
}
//map.forEach((value,key)=>{
// console.log(value,key)
//})
7、序列化
Object 类型可以通过Json.stringify() 进行序列化操作
const obj ={};
obj.name = 'zhangsan';
obj['age']=18
console.log("序列化前:",obj) //{ age: 18, name: "zhangsan" }
const obj1=JSON.stringify(obj)
console.log("序列化后:",obj1) // {"name":"zhangsan","age":18}
Map 结果不能直接进行JSON 序列化,会直接返回 {} 空对象
const map =new Map([
['name','zhangsan'],
['age',18]
]);
const map1 = JSON.stringify(Array.from(map))
console.log("序列化后:",map1) // "[["name","zhangsan"],["age",18]]"
8、适合场景
Object
1.仅做数据存储,并且属性仅为字符串或者Symbol。
2.需要进行序列化转换为json 传输时。
3.当做一个对象的实例,需要保留自己的属性和方法时。
Map
1.会频繁更新和删除键值对时。无论有多少数据,访问的时间复O(I),因为不需要扫描所以数据。
2.存储大量数据时,尤其是key类型未知的情况下
3.需要频繁进行迭代处理