描述
- Map和Set是ES6标准新增的数据类型,主要的应用场景在于数组去重和数据存储。
- 一个Map对象在迭代时会根据对象中元素的插入顺序来进行。
- 一个 for…of 循环在每次迭代后会返回一个形式为[key,value]的数组。
键的相等(Key equality)
- 键的比较是基于 sameValueZero 算法:
NaN 是与 NaN 相等的(虽然 NaN !== NaN),剩下所有其它的值是根据 === 运算符的结果判断是否相等。 - 在目前的ECMAScript规范中,-0和+0被认为是相等的,尽管这在早期的草案中并不是这样。
Map与Object
Map | Object | |
---|---|---|
意外的键 | 默认情况不包含任何键。只包含显式插入的键。 | 一个 Object 有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。 |
键的类型 | 键可以是任意值,包括函数、对象或任意基本类型。 | 键必须是一个 String 或是Symbol。 |
键的顺序 | key 是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。 | 键是无序的。 |
size | 可以直接通过size 属性获取 | 只能手动计算 |
迭代 | 可以直接被迭代 | 需要以某种方式获取它的键然后才能迭代 |
性能 | 在频繁增删键值对的场景下表现更好。 | 在频繁添加和删除键值对的场景下未作出优化。 |
实例
- Map.prototype.constructor
返回一个函数,它创建了实例的原型。默认是Map函数。 - Map.prototype.size
返回Map对象的键/值对的数量。
方法
- Map.prototype.clear()
移除Map对象的所有键/值对 。 - Map.prototype.delete(key)
如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false。随后调用 Map.prototype.has(key) 将返回 false 。 - Map.prototype.entries()
返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。 - Map.prototype.forEach(callbackFn[, thisArg])
按插入顺序,为 Map对象里的每一键值对调用一次callbackFn函数。如果为forEach提供了thisArg,它将在每次回调中作为this值。 - Map.prototype.get(key)
返回键对应的值,如果不存在,则返回undefined。 - Map.prototype.has(key)
返回一个布尔值,表示Map实例是否包含键对应的值。 - Map.prototype.keys()
返回一个新的 Iterator对象, 它按插入顺序包含了Map对象中每个元素的键 。 - Map.prototype.set(key, value)
设置Map对象中键的值。返回该Map对象。 - Map.prototype.values()
返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值 。 - Map.prototype@@iterator
返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。
示例
- 将 NaN 作为 Map 的键
NaN 也可以作为Map对象的键。虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true),但下面的例子表明,NaN作为Map的键来说是没有区别的:
let myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN); // "not a number"
let otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"
- Map 与数组
let kvArray = [["key1", "value1"], ["key2", "value2"]];
// 使用常规的Map构造函数可以将一个二维键值对数组转换成一个Map对象
let myMap = new Map(kvArray);
myMap.get("key1"); // 返回值为 "value1"
// 使用Array.from函数可以将一个Map对象转换成一个二维键值对数组
console.log(Array.from(myMap)); // 输出和kvArray相同的数组
// 更简洁的方法来做如上同样的事情,使用展开运算符
console.log([...myMap]);
// 或者在键或者值的迭代器上使用Array.from,进而得到只含有键或者值的数组
console.log(Array.from(myMap.keys())); // 输出 ["key1", "key2"]
- Maps合并
Maps对象间合并,会保持键的唯一性:
let first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let second = new Map([
[1, 'uno'],
[2, 'dos']
]);
// 合并两个Map对象时,如果有重复的键值,则后面的会覆盖前面的。
// 展开运算符本质上是将Map对象转换成数组。
let merged = new Map([...first, ...second]);
console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
Map对象与数组合并,如果有重复的键值,则后面的会覆盖前面的:
let first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let second = new Map([
[1, 'uno'],
[2, 'dos']
]);
// Map对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的。
let merged = new Map([...first, ...second, [1, 'eins']]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three