使用区别
-
键类型不同:Object的键只能使用string、number、symbol,Map的键可以是任何类型。
-
迭代顺序不同:
-
Map按照键值对插入顺序迭代
-
Object的迭代顺序:
- for-in循环和Object.keys()根据浏览器有不同表现
- Object.assign()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()枚举顺序确定,先升序枚举数值键,后插入顺序枚举字符串和symbol键。
-
性能区别
(测试数据基于chrome,速度测试使用performance.now()函数判断,内存使用情况使用Chrome devtool中的memory来查看)
-
内存占用
- Object内存占用更高。存储单个键值对所占用的内存空间随着键数量线性增加,所以给定相同大小的内存空间,Map大约比Object多存储50%的键值对。
let n, o, m; n = 10000; while (n--) { o = new Object({ 'a': 1, 'a1': 1, 'a2': 1, 'a3': 1, 'a4': 1, 'a5': 1, 'a6': 1, }); } n = 10000; while (n--) { m = new Map([['a', 1], ['a1', 1], ['a2', 1], ['a3', 1], ['a4', 1], ['a5', 1], ['a6', 1]]); } // 内存 class Test { } let test = new Test(); test.o = o; test.m = m;主要观察‘保留的大小’列:
-
插入性能
- Map插入速度更快。因为对于两个类型来说,插入速度不是随着键值对的数量呈线性增加,所以对于涉及大量插入操作Map更好。
let n, n2 = 5, o = new Object(), m = new Map(); // 速度 while (n2--) { let p1 = performance.now(); n = 10000; while (n--) { o[Math.random()] = Math.random(); } let p2 = performance.now(); n = 10000; while (n--) { m.set(Math.random(), Math.random()); } let p3 = performance.now(); console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`); } -
查找速度
- 查找速度差别不大。但是在对象键是连续整数的情况下,浏览器会优化处理,第二个测试案例结果可以看出,速度明显比Map快。所以涉及大量查找操作,Object表现更佳。
let n, n2 = 5, o = new Object(), m = new Map(); n = 10000; while (n--) { o[Math.random()] = Math.random(); } n = 10000; while (n--) { m.set(Math.random(), Math.random()); } // 速度 while (n2--) { let p1 = performance.now(); for (let i in o) { let k = o[i]; } let p2 = performance.now(); for (let [key] of m) { let k = m.get(key); } let p3 = performance.now(); console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`); }let n, n2 = 5, o = new Object(), m = new Map(); n = 10000; while (n--) { o[n] = Math.random(); } n = 10000; while (n--) { m.set(n, Math.random()); } // 速度 while (n2--) { let p1 = performance.now(); for (let i in o) { let k = o[i]; } let p2 = performance.now(); for (let [key] of m) { let k = m.get(key); } let p3 = performance.now(); console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`); } -
删除性能
- 测试结果差异不大。但是高程设计4中表述,Map的删除操作要快于插入和查找,所以Map的删除性能是高于Object的。
let n, n2 = 5, o = new Object(), m = new Map(); // 速度 while (n2--) { n = 10000; while (n--) { o[Math.random()] = Math.random(); } n = 10000; while (n--) { m.set(Math.random(), Math.random()); } let p1 = performance.now(); for (let i in o) { delete o[i]; } let p2 = performance.now(); for (let [key] of m) { m.delete(key); } let p3 = performance.now(); console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`); }
如何选择
- 选择Map
- 键值类型是string、number、symbol以外的,需要Map,因为Object不支持
- 迭代时需要保持插入顺序,选择Map,Object是无序的。
- 需要存储大量数据时选择Map,相同内存Map存的更多。
- 需要大量插入删除操作,选择Map,更快
- 选择Object
- 需要JSON转换,使用Object,Map不能直接转换。
- 需要大量查找操作,使用Object,更快
- 需要覆盖原型的键,使用Object。