
 
    概览:
 
 
     前沿
 
        一直以来使用数组和对象来定义数据模型,前几天在翻阅ES6语法的时候,突然发现有一种Map对象对操作键值对特别好用,而且代码更简洁明了,简直太棒了。今天,我们就来一步步了解什么是Map对象,详细给大家介绍一下Map对象的属性和方法。希望大家以后再数据操纵方法多一种解决问题的方法,这是ECMAScript 6 新增的数据结构。
 
     定义
 
   Map对象保存键/值对,是键/值对的集合。任何值(对象或者原始值) 都可以作为一个键或一个值。Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应。
 
     语法
 
mapObj = new Map([iterable]);
 
         iterable 可以是一个数组或者其他 iterable 对象,其元素或为键值对,或为两个元素的数组。 每个键值对都会添加到新的 Map。null 会被当做 undefined。
 
     描述
 
 
 -         集合中的键和值可以是任何类型。如果使用现有键向集合添加值,则新值会替换旧值。
-         Object 和 Map 对象的对比:
            相似点: 都允许你按键存取一个值、删除键、检测一个键是否绑定了值。
             不同点:
 
                       1. 一个对象的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值,包括函数、对象、基本类型。
                        2. Map 中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map对象是按插入的顺序返回键值。
                        3. 通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值对个数只能手动计算。
                        4. Map 是可迭代的,而 Object 的迭代需要先获取它的键数组然后再进行迭代。
                        5. Object 都有自己的原型,所以原型链上的键名有可能和对象上的键名产生冲突。虽然 ES5 开始可以用 map = Object.create(null) 来创建一个没有原型的对象,但是这种用法不太常见。
                        6. Map 在频繁增删键值对的场景下会有些性能优势。
 
    属性
 
                下表列出了Map对象的属性
 
 
  
   
   | 属性 | 描述 | 
 
  
  
   
   | 构造函数 - get Map[@@species] | 指定创建映射的函数,本构造函数用于创建派生对象。 | 
 
   
   | 原型(Map.prototype) | 为映射返回对原型的引用, 表示Map构造器的原型。 允许添加属性从而应用于所有的Map对象。 | 
 
   
   | size (Map.length) | 返回映射中的元素数。 | 
 
  
 
    Map实例
 
           所有的Map实例都会继承自Map.prototype。
 
        属性
 
                     下表列出了Map对象实例的属性
 
 
  
   
   | 属性 | 描述 | 
 
  
  
   
   | Map.prototype.constructor | 返回一个函数,它创建了实例的原型。默认是Map函数。 | 
 
   
   | Map.prototype.size | 返回Map对象的键/值对的数量。 | 
 
  
 
 
 
        方法
 
                    下表列出了Map对象实例的方法
 
 
 
 
        示例
 
                     Map对象类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
 
let a = new Map();
let b = {p: 'Hello World'};
a.set(b,"content");
a.get(b);                 //"content"
a.has(b);                //true
a.delete(b);             //true
a.has(b);                //false
 
                作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
 
let map = new Map([
  ['first', 'aaaaaaaaaaaaa'],
  ['second','bbbbbbbbbbbbb']
]);
map.size();                 // 2
map.has('first');           // true
map.get('first');           // "aaaaaaaaaaaaa"
map.has('second');          // true
map.get('second');          // "bbbbbbbbbbbbb"
 
               如果对同一个键多次赋值,后面的值将覆盖前面的值。
 
let map = new Map();
map.set(1, 'aaa');
map.set(1, 'bbb');
map.get(1)         
// "bbb"
 
                如果读取一个未知的键,则返回undefined。!!!注意,只有对同一个对象的引用,Map结构才将其视为同一个键。Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
 
let map =new Map();
map.get('abc');         // undefined
map.set(['a'], 555);
map.get(['a'])          // undefined
const k1 = ['a'];
const k2 = ['a'];
map
.set(k1, 111)
.set(k2, 222);
map.get(k1);            // 111
map.get(k2);            // 222
 
                  Map.clear() 方法清除所有成员,没有返回值。
 
let map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size();             // 2
map.clear();          
map.size();             // 0
 
                  Map对象遍历方法示例
 
let  map = new Map([
  ['first',  'aaa'],
  ['second',  'bbb'],
]);
// map.keys()方法
for (let key of map.keys()) {
  console.log(key);
}
//  first
//  second
// map.values()方法
for (let value of map.values()) {
  console.log(value);
}
// "aaa"
// "bbb"
//map.entries() 方法
for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "first"  "aaa"
// "second"  "bbb"
//等同于使用map.entries()方法
for (let [key, value] of map) {
  console.log(key, value);
}
// "first"   "aaa"
// "second"  "bbb"
//数组结构可以使用扩展运算符(...)
[...map.keys()]
//["first","second"]
[...map.values()]
// ["aaa","bbb"]
[...map.entries()]
// [["first",  "aaa"],["second",  "bbb"]]
[...map]
//[["first",  "aaa"],["second",  "bbb"]]
 
                结合数组的map() 和filter()方法,可以实现对Map的遍历和过滤(Map本身没有map()和filter()方法)
 
let  myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
let newMap = new Map(
  [...myMap].filter(([key, value]) => value < 3)
);
// Map(2) {"thing1" => 1, "thing2" => 2}
let newMap2 = new Map(
  [...myMap].map(([key, value]) => [key, value * 2])
    );
// Map(3) {"thing1" => 2, "thing2" => 4, "thing3" => 6}
 
                 Map对象还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。
 
let map = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
map.forEach(function(value, key, map) {
  console.log("Key: %s, Value: %s", key, value);
});
// Key: thing1, Value: 1
// Key: thing2, Value: 2
// Key: thing3, Value: 3
 
                forEach方法还可以接受第二个参数,用来绑定this。
 
let map = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
let reporter = {
  report: function(key, value) {
    console.log("Key: %s, Value: %s", key, value);
  }
};
map.forEach(function(value, key, map) {
  this.report(key, value);
}, reporter);
// Key: thing1, Value: 1
// Key: thing2, Value: 2
// Key: thing3, Value: 3
 
 
 
 
 
    参考文献
 
 
          转载时请注明:来自w-rain的个人博客