Skip to content

map和object的区别?对相同操作他们的性能有差异吗?

🕒 Published at:

map和object的区别?

  1. object的key只能是字符串或者Symbol,而map的key可以是任意类型
  2. map的遍历顺序是其添加顺序,而object则不一定
  3. map可以使用for...of遍历,而object不能,是因为map部署了Symbol(Symbol.iterator)接口,而object没有
  4. Map.prototype.__proto__ === Object.prototype 为true,可以看出Map.prototype和Object.prototype的关系
  5. Object.prototype.toString.call(new Map())返回[object Map],而Object.prototype.toString.call(new Object())返回[object Object]

性能差异

  1. 当key为有序连续的整数时,Object的性能优于Map;(V8对Object在键为有序连续正整数时做了优化)
  2. 当key为字符串、非有序连续整数、Symbol时Map的 添加 和 读取 性能优于Object,修改 和 删除 操作性能相差不大;(Object会把键转为String类型,消耗了一部分性能)
  3. 当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,删:271ms
js
// 当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。