ES6的Map函数详解
一、Map介绍
Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者基本类型)都可以作为一个键或一个值
Map 对象是键值对的集合。Map 中的一个键只能出现一次;它在 Map 的集合中是独一无二的。Map 对象在for…of 循环在每次迭代后会返回一个形式为 [key,value] 的数组
二、简单的使用
const map1 = new Map(); map1.set('a', 1); map1.set('b', 2); map1.set('c', 3); // map取值 console.log(map1.get('a')); // 1 // 可以覆盖 map1.set('a', 97); console.log(map1.get('a')); // 97 // 类似 数组的 length console.log(map1.size); // 3 // map 删除 map1.delete('b'); console.log(map1.size); // 2
三、Object 和 Map 的比较
四、实例属性介绍
4.1. Map.prototype.size
返回 Map 对象中的键值对数量。
const map = new Map() map.set('name','张三') map.size // 1
五、实例方法介绍
5.1. Map.prototype.clear()
移除 Map 对象中所有的键值对。
const myMap = new Map(); myMap.set('bar', 'baz'); myMap.set(1, 'foo'); console.log(myMap.size); // 2 myMap.clear(); console.log(myMap.size); // 0
5.2. Map.prototype.delete()
移除 Map 对象中指定的键值对,如果键值对存在并成功被移除,返回 true,否则返回 false。调用 delete 后再调用 map.has(key) 将返回 false
const myMap = new Map(); myMap.set("bar", "foo"); console.log(myMap.delete("bar")); // 返回 true。成功地移除元素 console.log(myMap.has("bar")); // 返回 false。"bar" 元素将不再存在于 Map 实例中 console.log(myMap.size) // 0 console.log(myMap.get('bar')) // undefined
5.3. Map.prototype.get()
返回与指定的键 key 关联的值,若不存在关联的值,则返回 undefined
const myMap = new Map(); myMap.set("bar", "foo"); console.log(myMap.get('bar')) // foo myMap.delete("bar") console.log(myMap.get('bar')) // undefined
5.4. Map.prototype.has()
返回一个布尔值,用来表明 Map 对象中是否存在与指定的键 key 关联的值
const myMap = new Map(); myMap.set("bar", "foo"); console.log(myMap.has("bar")); // true console.log(myMap.has("baz")); // false
5.5. Map.prototype.set()
在 Map 对象中设置与指定的键 key 关联的值,并返回 Map 对象
const myMap = new Map(); // 将一个新元素添加到 Map 对象 myMap.set('bar', 'foo'); myMap.set(1, 'foobar'); // 在 Map 对象中更新某个元素的值 myMap.set('bar', 'baz'); // 链式调用添加元素 myMap.set('bar', 'foo') .set(1, 'foobar') .set(2, 'baz');
5.6. Map.prototype.keys()
返回一个新的迭代对象,其中包含 Map 对象中所有的键,并以插入 Map 对象的顺序排列
var myMap = new Map(); myMap.set('0', 'foo'); myMap.set(1, 'bar'); myMap.set({}, 'baz'); const mapIter = myMap.keys(); for (const entry of myMap.keys()) { console.log(entry); // 0 // 1 // {} }
5.7. Map.prototype.values()
返回一个新的迭代对象,其中包含 Map 对象中所有的值
const myMap = new Map(); myMap.set('0', 'foo'); myMap.set(1, 'bar'); myMap.set({}, 'baz'); const mapIter = myMap.values(); for (const entry of myMap.values()) { console.log(entry); // foo // bar // baz }
5.8. Map.prototype.entries()
返回一个新的迭代对象,其为一个包含 Map 对象中所有键值对的 [key, value] 数组,并以插入 Map 对象的顺序排列
const myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); const mapIter = myMap.entries(); for (const entry of myMap.entries()) { console.log(entry); // ["0", "foo"] // [1, "bar"] // [{}, "baz"] }
map实例本身就是一个可迭代的entries
const myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); for (const entry of myMap) { console.log(entry); // ["0", "foo"] // [1, "bar"] // [{}, "baz"] }
5.9. Map.prototype.forEach()
以插入的顺序对 Map 对象中存在的键值对分别调用一次 callbackFn。如果给定了 thisArg 参数,这个参数将会是回调函数中 this 的值
const myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); myMap.forEach((value, key, map) => { console.log(value, key, map); // foo 0 可迭代的 map // bar 1 可迭代的 map // baz {} 可迭代的 map for (const inter of map) { console.log(inter); //["0", "foo"] //[1, "bar"] //[{}, "baz"] } })
六、其他
6.1. 将 NaN 作为 Map 的键
NaN 也可以作为 Map 对象的键。虽然 NaN 与任何值甚至与自己都不相等(NaN !== NaN 返回 true),但是因为所有的 NaN 的值都是无法区分的,所以下面的例子成立:
const myMap = new Map(); myMap.set(NaN, 'not a number'); myMap.get(NaN); // "not a number" const otherNaN = Number('foo'); myMap.get(otherNaN); // "not a number"
6.2. 使用 for…of 方法迭代 Map
Map 可以使用 for…of 循环来实现迭代:
const myMap = new Map(); myMap.set(0, 'zero'); myMap.set(1, 'one'); for (const [key, value] of myMap) { console.log(`${key} = ${value}`); } // 0 = zero // 1 = one for (const key of myMap.keys()) { console.log(key); } // 0 // 1 for (const value of myMap.values()) { console.log(value); } // zero // one for (const [key, value] of myMap.entries()) { console.log(`${key} = ${value}`); } // 0 = zero // 1 = one
6.3. Map 与数组的关系
const kvArray = [['key1', 'value1'], ['key2', 'value2']]; // 使用常规的 Map 构造函数可以将一个二维键值对数组转换成一个 Map 对象 const myMap = new Map(kvArray); console.log(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"]
6.4. 复制或合并 Maps
// Map 能像数组一样被复制: const original = new Map([ [1, 'one'], ]); const clone = new Map(original); console.log(clone.get(1)); // one console.log(original === clone); // false. 浅比较 不为同一个对象的引用 //Map 对象间可以进行合并,但是会保持键的唯一性。 const first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]); const second = new Map([ [1, 'uno'], [2, 'dos'] ]); // 合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的。 // 展开语法本质上是将 Map 对象转换成数组。 const merged = new Map([...first, ...second]); console.log(merged.get(1)); // uno console.log(merged.get(2)); // dos console.log(merged.get(3)); // three // Map 对象也能与数组合并: const first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]); const second = new Map([ [1, 'uno'], [2, 'dos'] ]); // Map 对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的。 const 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