[TOC]
* * * * *
>[info] `Map` 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
### 一. `Map` 和 普通对象
>[info] `Object` 和 `Map` 类似的一点是,它们都允许你按键存取一个值,都可以删除键,还可以检测一个键是否绑定了值。因此,一直以来,我们都把对象当成Map来使用。
现在有了 `Map` ,下面的区别解释了为什么使用 `Map` 更好点.
~~~
a. 一个对象通常都有自己的原型,所以一个对象总有一个 'prototype' 键。不过,从 ES5 开始可以使用 map = Object.create(null) 来创建一个没有原型的对象。
b. 一个对象的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
c. 你可以通过 size 属性很容易地得到一个 Map 的键值对个数,而对象的键值对个数只能手动确认。
~~~
>[info] 但是这并不意味着你可以随意使用 `Map`,对象仍旧是最常用的。
`Map` 实例只适合用于集合 `(collections)`,你应当考虑修改你原来的代码——先前使用对象来处理集合的地方。对象应该用其字段和方法来作为记录的。
进一步确认是需要用什么:
~~~
a. 在运行之前 key 是否是未知的,是否需要动态地查询 key 呢?
b. 是否所有的值都是统一类型,这些值可以互换么?
c. 是否需要不是字符串类型的 key ?
d. 键值对经常增加或者删除么?
e. 是否有任意个且非常容易改变的键值对?
f. 这个集合可以遍历么 (Is the collection iterated) ?
~~~
假如以上全是“是”的话,那么你需要用 Map 来保存这个集。
相反,你有固定数目的键值对,独立操作它们,区分它们的用法,那么你需要的是对象。
* * * * *
### 二. 语法
#### 1. 构造 `Map` 对象
~~~
<1>. 使用字面量构造,代码量少
var f1=function() {},
o1={},
s1=Symbol('rc');
var m1=new Map([
[1,'number'],
['name','wdd'],
[f1,'a function.'],
[o1,'a object'],
[s1,'a Symbol']
]);
<2>. 调用方法,一个一个插入
var m2=new Map();
m2.set(key, value);
~~~
#### 4. `Map.prototype.size`
返回Map对象的键/值对的数量。
![](https://box.kancloud.cn/85a4568e158512da5ffda38634117e30_278x335.png)
#### 5. `Map.prototype.clear()`
移除Map对象的所有键/值对 。
![](https://box.kancloud.cn/e7e9590ed1cb846b30e6244d28595493_233x354.png)
#### 6. `Map.prototype.delete(key)`
~~~
移除任何与键相关联的值,并且返回该值,该值在之前会被
Map.prototype.has(key) 返回为 true 。之后再调用
Map.prototype.has(key) 会返回 false 。
~~~
![](https://box.kancloud.cn/edd31c890ab659978f7e8a98ba44182d_166x175.png)
#### 7. `Map.prototype.entries()`
返回一个新的 `Iterator` 对象,它按插入顺序包含了 `Map` 对象中每个元素的 `[key, value]` 数组。
#### 8. `Map.prototype.forEach(callbackFn[, thisArg])`
~~~
按插入顺序,为 Map 对象里的每一键值对调用一次 callbackFn 函数。
如果为 forEach 提供了 thisArg,它将在每次回调中作为 this 值。
~~~
#### 9. `Map.prototype.get(key)`
返回键对应的值,如果不存在,则返回 `undefined` 。
#### 10. `Map.prototype.has(key)`
返回一个布尔值,表示Map实例是否包含键对应的值。
![](https://box.kancloud.cn/9817489ce63a7ec9c0705a7e3effa577_190x114.png)
#### 11. `Map.prototype.keys()`
返回一个新的 `Iterator` 对象, 它按插入顺序包含了 `Map` 对象中每个元素的键 。
#### 12. `Map.prototype.set(key, value)`
设置 `Map` 对象中键的值。返回该 `Map` 对象。
#### 13. `Map.prototype.values()`
返回一个新的 `Iterator` 对象,它按插入顺序包含了 `Map` 对象中每个元素的值 。
#### 14. `Map.prototype[@@iterator]()`
返回一个新的 `Iterator` 对象,它按插入顺序包含了 `Map` 对象中每个元素的 `[key, value]` 数组。
#### 15. 键值为 `NaN`
~~~
map中的键值如果为 NaN ,那么只要一个值为 NaN ,就可以取出对应的值
(按标准,任何两个NaN都是不相等的);对于其他的键,一律以 === 规则来判断。
~~~
![](https://box.kancloud.cn/bd52af9ed246ad8f245a6d4d8580bca3_123x58.png)
~~~
var m2 = new Map();
m2.set(NaN, "not a number");
m2.get(NaN); // "not a number"
var otherNaN = Number("foo");
m2.get(otherNaN); // "not a number"
~~~
### 三. 遍历 `Map`
#### 1. `of` 操作符
可见每一个元素都是一个含有两个值得数组,就和用字面量组装时候的一样。
![](https://box.kancloud.cn/26122f3ae67cee09b5362edeadc5d3b9_311x204.png)
#### 2. 只遍历键或值
![](https://box.kancloud.cn/de4c80476c2dfb57fa062896d757522a_671x81.png)
![](https://box.kancloud.cn/7c6bbfa9cd174dc279f8f34bd3c7e81b_355x412.png)
#### 3. `forEach` 方法
![](https://box.kancloud.cn/96142018c5df34afff44618f71768ed3_374x202.png)
>[danger] PS:`Map.keys(), Map.values(), Map.entries()` 这三个在 IE 11 中没有实现,其他浏览器没问题