map和object的区别?
- object的key只能是字符串或者Symbol,而map的key可以是任意类型
- map的遍历顺序是其添加顺序,而object则不一定
- map可以使用for...of遍历,而object不能,是因为map部署了Symbol(Symbol.iterator)接口,而object没有
Map.prototype.__proto__ === Object.prototype为true,可以看出Map.prototype和Object.prototype的关系Object.prototype.toString.call(new Map())返回[object Map],而Object.prototype.toString.call(new Object())返回[object Object]
性能差异
- 当key为有序连续的整数时,Object的性能优于Map;(V8对Object在键为有序连续正整数时做了优化)
- 当key为字符串、非有序连续整数、Symbol时Map的 添加 和 读取 性能优于Object,修改 和 删除 操作性能相差不大;(Object会把键转为String类型,消耗了一部分性能)
- 当key为其他数据类型时,只能选择Map;(Object的键只能为string、symbol类型)
测试代码
js
// 当key为字符串、非有序连续整数、Symbol时Map的 添加 和 读取 性能优于Object,修改 和 删除 操作性能相差不大;
function createRandomKey() {
return new Date().getTime().toString().substring(6, 13) + '-' + (Math.random() * 100000000).toString().substring(0, 7);
}
let keys = []
function setKeys() {
for (let i = 0; i < 1000000; i++) {
keys.push(createRandomKey())
}
}
setKeys()
let obj = new Object()
let map = new Map()
function getObjectTimeDiff() {
let t1 = new Date().getTime()
// 增
for (let i in keys) {
obj[keys[i]] = i
}
let t2 = new Date().getTime()
// 读
for (let j in keys) {
let value = obj[keys[j]]
}
let t3 = new Date().getTime()
// 改
for (let k in keys) {
obj[keys[k]] = keys[k]
}
let t4 = new Date().getTime()
// 删
for (let l in keys) {
delete obj[keys[l]]
}
let t5 = new Date().getTime()
return `object 增:${t2 - t1}ms,读:${t3 - t2}ms,改:${t4 - t3}ms,删:${t5 - t4}ms`
}
function getMapTimeDiff() {
let t1 = new Date().getTime()
for (let i in keys) {
map.set(keys[i], i)
}
let t2 = new Date().getTime()
for (let j in keys) {
let value = map.get(keys[j])
}
let t3 = new Date().getTime()
for (let k in keys) {
map.set(keys[k], keys[k])
}
let t4 = new Date().getTime()
for (let l in keys) {
map.delete(keys[l])
}
let t5 = new Date().getTime()
return `map 增:${t2 - t1}ms,读:${t3 - t2}ms,改:${t4 - t3}ms,删:${t5 - t4}ms`
}
console.log(getObjectTimeDiff())
console.log(getMapTimeDiff())
// object 增:610ms,读:158ms,改:166ms,删:158ms
// map 增:411ms,读:100ms,改:228ms,删:271msjs
// 当key为有序连续的整数时,Object的性能优于Map;(V8对Object在键为有序连续正整数时做了优化)
let keys = []
function setKeys() {
for (let i = 0; i < 1000000; i++) {
keys.push(i)
}
}
setKeys()
let obj = new Object()
let map = new Map()
function getObjectTimeDiff() {
let t1 = new Date().getTime()
for (let i in keys) {
obj[keys[i]] = i
}
let t2 = new Date().getTime()
for (let j in keys) {
let value = obj[keys[j]]
}
let t3 = new Date().getTime()
for (let k in keys) {
obj[keys[k]] = keys[k]
}
let t4 = new Date().getTime()
for (let l in keys) {
delete obj[keys[l]]
}
let t5 = new Date().getTime()
return `object 增:${t2 - t1}ms,读:${t3 - t2}ms,改:${t4 - t3}ms,删:${
t5 - t4
}ms`
}
function getMapTimeDiff() {
let t1 = new Date().getTime()
for (let i in keys) {
map.set(keys[i], i)
}
let t2 = new Date().getTime()
for (let j in keys) {
let value = map.get(keys[j])
}
let t3 = new Date().getTime()
for (let k in keys) {
map.set(keys[k], keys[k])
}
let t4 = new Date().getTime()
for (let l in keys) {
map.delete(keys[l])
}
let t5 = new Date().getTime()
return `map 增:${t2 - t1}ms,读:${t3 - t2}ms,改:${t4 - t3}ms,删:${
t5 - t4
}ms`
}
console.log(getObjectTimeDiff())
console.log(getMapTimeDiff())
// object 增:102ms,读:66ms,改:56ms,删:118ms
// map 增:186ms,读:115ms,改:114ms,删:156ms结论:针对大量增和读的场景下,map性能更好,其他情况如果能使用object,则使用object。