典型的区别
Map可以将任何数据类型作为key,而Object,只能使用String或者Symbol。
一个 Map的键可以是任意值,包括函数、对象或任意基本类型。
const map = new Map();
map.set(NaN, 'NaN');
map.get(NaN) // NaN
map.set(null, 'null');
map.get(null) // null
map.set(undefined, '未定义');
map.get() // 未定义
Map的键是按插入顺序排序的,而Object并非总是按插入顺序
实际上Object的key顺序也是有规则(或说有顺序)的。可以理解为键的排序分为三组,各自排序:
- 数值类型,比如’1’, ‘2’
- 字符串类型, 比如’foo’, ‘bar’
- Symbol类型
每组内按插入顺序排序,比如
const obj = {};
obj.b = 'b';
obj.a = 'a';
obj[1] = 1;
obj[Symbol('foo')] = 'symbol foo';
obj[2] = 2;
obj[Symbol('bar')] = 'symbol bar';
console.log(obj)
// {1: 1, 2: 2, b: "b", a: "a", Symbol(foo): "symbol foo", Symbol(bar): "symbol bar"}
细微的差别
- Map实现了
Iterator
接口,可以直接使用for of
进行遍历。而Object需要使用Object.entries()
等类似的方法 - Map可以直接使用
size
方法得到entries的长度,而Object由于在创建的时候包含的原型属性,固求长度需要单独处理
性能差别
Map相对于Obj还是快的:
const benchmarkMap = size => {
console.time('benchmarkMap');
var map = new Map();
for (var i = 0; i < size; i++) map.set(i+'s', i);
for (var i = 0; i < size; i++) var x = map.get(i+'s');
console.timeEnd('benchmarkMap');
}
const benchmarkObj = size => {
console.time('benchmarkObj');
var obj = {};
for (var i = 0; i < size; i++) obj[i+'s'] = i;
for (var i = 0; i < size; i++) var x = obj[i+'s'];
console.timeEnd('benchmarkObj');
}
var size = 1000000;
benchmarkMap(size);
benchmarkObj(size);
// 结果
benchmarkMap: 764.6181640625 ms
benchmarkObj: 1443.76806640625 ms
// 值得注意的是,之所以key是i+'s'是因为,Object对key是数字的情况做了优化。
MDN还提到在频繁增删的情况下Map表现会更好:
Map: 在频繁增删键值对的场景下表现更好。
Object: 在频繁添加和删除键值对的场景下未作出优化。
参考
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map