JavaScript 里 Object 和 Map 的区别

JavaScript 里 Object 和 Map 的区别,第1张

Object 和 Map 定义

Object 是最常用的一种引用类型数据,可用于存储键值对的集合,在 ECMAScript 1st 出现的

// 定义
const obj = {
  a: 1,
  b: 2
}
// 添加键值对
obj.c = 3
// 删除键值对
delete obj.a
console.log(obj)

Map 是键值对的集合,采用的 Hash 结构存储,在 ECMAScript 2015(ES6) 版本添加的

// 定义
const map = new Map()
// 添加键值对
map.set('a', 1)
map.set('b', 2)
// 删除键值对
map.delete('a')
console.log(map)

不同点

1.构造方式

Object

// 对象字面量
const obj = {
  a: 1,
  b: 2
}

// 构造方法
const o = new Object()

// 生成一个Object实例 Object.create()

Map

// 构造方法
const m = new Map()
const m2 = new Map([
  ['a', '1'],
  ['b', '2']
]) // 传递初始值就需要传递一个二维数组的形式,里面的元素就是一个一维数组

键的类型

Object 键类型必须是String或者Symbol,如果非String类型,会进数据类型转换

// 例1:
const obj2 = {
	a: 1
}
const arr = [1, 2]
obj2[arr] = 'arr' // 会调用这个数组的 toSting 方法,转换成字符串,作为它的属性值
console.log(obj2) // {a: 1, 1,2: 'arr'}

// 例2:
obj2[3] = 3
obj2['3'] = 33  // 数字类型的3和字符串的3会当成同一个值来处理,后面的会覆盖前面的
console.log(obj2) // {3: 33, a: 1, 1,2: 'arr'}

Map 可以是任意类型,包括对象,数组,函数等,不会进行类型转换
在添加键值对时,会通过严格的相等(===)来判断键属性是否已存在

// 例:
const map2 = new Map()
map2.set('a', 1)
map2.set('2', '2')
map2.set(2, 2)
map2.set(arr, 'arr')
console.log(map2)

// Map 的特例: NaN
// NaN === NaN (false)
// Map 使用 NaN 形式赋值的时候,后面的键会覆盖前面的(可以理解为键被覆盖了,也可以说是值被覆盖了,反正都是因为 NaN 的特性),只会被覆盖掉
map2.set(NaN, 1)
map2.set(NaN, 2)
console.log(map2) // 后面的覆盖前面的,值被覆盖掉了


3.键的顺序

Object key 是无序的,不会按照添加的顺序返回
1.对于大于等于0的整数,会按照大小进行排序,对应小数和负数会当做字符串处理数字优先于字符串
2.对应String类型,按照定义的顺序进行输出
3.对于Symbol类型,会直接过滤掉,不会进行输出,如果想要输出Symbol类型的属性,需要通过Object.getOwnPropertySymbols()方法

const obj3 = {
  2: 2,
  '1': 1, // '1'被当成了数字1处理
  'b': 'b',
  1.1: 1.1,
  0: 0,
  'a': 'a',
  [Symbol('s1')]: 's1',
  [Symbol('s2')]: 's2'
}
console.log(obj3)
console.log(Object.keys(obj3))
console.log(Object.getOwnPropertySymbols(obj3))

Map key是有序的,按照插入的顺序进行返回

const map3 = new Map()
map3.set(2, 2)
map3.set('1', 1)
map3.set('b', 'b')
map3.set(1.1, 1.1)
map3.set(0, 0)
map3.set('a', 'a')
map3.set(Symbol('s1'), 's1')
map3.set(Symbol('s2'), 's2')

console.log(map3.keys()) // 自带的 api 方法
for (let key of map3.keys()) {
  console.log(key)
}


4.键值对的 size

Object 只能手动计算,通过 Object.keys() 方法或者通过 for…in 循环统计

const obj4 = {
  2: 2,
  '1': 1,
  'b': 'b'
}
console.log(Object.keys(obj4).length) // 3
let count = 0
for (const i in obj4) {
  count++
}
console.log(count) // 3

Map 有对应的 api 直接通过 size 属性访问

const map4 = new Map()
map4.set(2, 2)
map4.set('1', 1)
map4.set('b', 'b')
console.log(map4.size) // 3

5.键值对的访问

Object

// 1. 添加或修改属性,通过点或者中括号的形式
const obj5 = new Object()
obj5.name = '哈哈哈'
obj5[Symbol('s5')] = 's5'
console.log(obj5)
// 2. 判断属性是否存在
// obj5.name === undefined
// obj5['name'] === undefined
// 3. 删除属性,通过delete关键字
delete obj5.name

Map 有对应的 api

// 1. 添加和修改 key-value
const map5 = new Map()
map5.set('name', '哈哈哈')
map5.set(Symbol('s5'), 's5')
console.log(map5)
// 2. 判断属性是否存在
// map.has('name') // true
// map.has('age') // false
// 3. 其他 API  *** 作
//    取值
//    map5.get('name') // 哈哈哈
//    删除键值对
//    map5.delete('name')
//    获取所有的属性名
//    map5.keys()
//    清空map
//    map5.clear()

6.迭代器

Object 本身不具有 Iterator 特性,默认情况下不能使用 for…or 进行遍历

const obj6 = {
  name: '哈哈哈',
  age: 14
}
// for (let key of obj6) { } // Uncaught TypeError: obj6 is not iterable

Map 结构的 keys(),values(),entries() 方法都是具有 Iterator 特性

const map6 = new Map([
  ['name', '哈哈哈'],
  ['age', 14]
])
console.log(map6) // Map
console.log(map6.entries()) // MapIterator,返回一个包含[key, value]新的 Iterator 对象
for (let [key, value] of map6.entries()) {
  console.log(key, value)
  // name 哈哈哈
  // age 14
}

7.JSON 序列化

Object 类型可以通过 JSON.stringIfy() 进行序列化 *** 作

const obj7 = {
   name: '哈哈哈',
   age: 14
 }
 console.log(JSON.stringify(obj7)) // '{"name":"哈哈哈","age":14}'

Map 结构不能直接进行 JSON 序列化

const map7 = new Map([
  ['name', '哈哈哈'],
  ['age', 14]
])
console.log(JSON.stringify(map7)) // '{}'
// 如果想要将一个 Map 结构序列化 *** 作的话
// 先将 map7 转成数组 Array.from(map7) 
// 再把转换的数组序列化
console.log(Array.from(map7))
console.log(JSON.stringify(Array.from(map7))) // '[["name","哈哈哈"],["age",14]]'

8.应用场景

Object
1.仅做数据存储,并且属性仅为字符串或者Symbol
2.需要进行序列化转换为json传输时
3.当做一个对象的实例,需要保留自身的属性和方法时

Map
1.会频繁的更新和删除键值对时
2.存储大量数据时,尤其是key类型未知的情况下
3.需要频繁进行迭代处理

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/946907.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存