ES6新增 Map

Map

(1)基本语法

javascript的对象(Object)本质上是键值对的集合,只能用字符串作为键名,对于其他的类型,会自动转为字符串:

    let array_ = [1, 2, 3, 4];//数组
    let function_ = function () {};//函数
    let number_=123;//数字
    let object_={};//对象

    let a = {};
    a[number_]="q";
    a[array_]="qe";
    a[function_]="qwe";
    a[object_]="qwer";

    let p = Object.keys(a);
    console.log(p);//["123","1,2,3,4","function(){}","[object object]"]
    console.log(typeof p[0]);//string
    console.log(typeof p[1]);//string
    console.log(typeof p[2]);//string
    console.log(typeof p[3]);//string

为了解决这个问题ES6提供了Map数据结构,它类似对象,也是键值对的集合,但是键名可以是各种类型:

    let number_=123;//数字
    let array_ = [1, 2, 3, 4];//数组
    let function_ = function () {};//函数
    let object_={};//对象

    const a=new Map();
    a.set(number_,"q");
    a.set(array_,"qw");
    a.set(function_ ,"qwe");
    a.set(object_,"qwer");
    
    a.get(number_);//q
    a.get(array_);//qw
    a.get(function_);//qwe
    a.get(object_);//qwer
    
    for(let key of a.keys()){
        console.log(typeof key);
    }
    //number 
    //object
    //function
    //object

上面用到了Map结构的get和set操作方法。

Map构造函数

任何具有Iterator接口,且每个成员都是一个双元素数组的数据结构都可以当作Map构造函数的参数。例如数组:

const map = new Map([
     [1,"one"],
     [2, "two"],
     [3, "three"]
 ]);
//     Map{
//     1 => "one",
//     2 => "two",
//     3 => "three"
// }

如果传入的数组成员是存在三个元素的数组,则会忽略第三个元素:

const map = new Map([
     [1,"one","_one"],
     [2, "two"],
     [3, "three"]
 ]);
//     Map{
//     1 => "one",
//     2 => "two",
//     3 => "three"
// }

数组的成员存在单元素数组:

   const map = new Map([
        [1],
        [2, "two"],
        [3, "three"]
    ]);
//     Map{
//     1 => undefined,
//     2 => "two",
//     3 => "three"
// }

除了数组,Map和Set都可以用来生成新的Map。

Map的键与内存地址绑定
const map=new Map();

//虽然k1和k2的值是相同的,但k1和k2存储的内存地址是不同的
const k1=["a"];
const k2=["a"];

map.set(k1,111)
   .set(k2,111);
  
map.get(k1);// 111
map.get(k2);// 222

Map的键与内存地址绑定,只要两个值的内存地址不同,Map就将它们视为两个键。

(2)实例属性和操作方法

1.size属性

size属性返回Map结构的成员总数

let a=new Map();
    a.set("1","q");
    a.set("2","qw");

   console.log(a.size)//2
2.set(key,value)

set方法设置键名(key)对应的键值(value),返回Map结构。如果设置的key已经有值,则键值会被更新。由于set方法返回的是当前的Map对象,因此可以采用链式写法:

let a=new Map();
    a.set("1","q")
     .set("2","qw")
     .set("3","qwe");
3.get(key)

get方法读取key所对应的键值,如果找不到key,返回undefined。

4.has(key)

has方法返回一个布尔值,表示某个键是否存在Map中。

5.delete(key)

delete方法删除某个键,返回true。如果删除失败,返回false。

6.clear()

clear方法清除所有成员,没有返回值。

(3)遍历方法

Map的遍历顺序就是插入顺序。

1.keys():返回键名的遍历器。
2.values():返回键值的遍历器。
3.entries():返回所有成员的遍历器。
const map = new Map([
        ["F", "NO"],
        ["T", "YES"]
    ]);

    for (let key of map.keys()) {
        console.log(key);
    }
    //"F"
    //"T"

    for (let value of map.values()) {
        console.log(value);
    }
    //"NO"
    //"YES"

    for (let item of map.entries()) {
        console.log(item[0],item[1]);
    }
    //"F" "NO"
    //"T" "YES"
    //或者
    for (let [key,value] of map.entries()) {
        console.log(key,value);
    }
    //"F" "NO"
    //"T" "YES"

    //和使用map.entries()相同
    for (let [key,value] of map) {
        console.log(key,value);
    }
    //"F" "NO"
    //"T" "YES"

Map结构的默认遍历器属性接口(Symbol.iterator属性)就是entries方法(在Set结构中默认遍历器生成函数是它的values方法)。

Map结构转为数组

Map结构转为数组结构的比较快速的方法是结合扩展运算符(…)。

 const map = new Map([
        ["1", "one"],
        ["2", "two"],
        ["3", "three"]
    ]);

    console.log([...map.keys()]);
    //["1","2","3"]

    console.log([...map.values()]);
    //["one","two","three"]

    console.log([...map.entries()]);
    //[["1","one"],["2","two"],["3","three"]]

    console.log([...map]);
    //[["1","one"],["2","two"],["3","three"]]
    
Map的遍历和过滤

Map本身没有map和filter方法,但是可以结合数组的map方法、filter方法,可以实现Map的遍历和过滤。

const map = new Map([
        [1, "one"],
        [2, "two"],
        [3, "three"]
    ]);


    const map1=new Map(
        [...map].filter(([k,v])=>k<3)
    );
    //产生map结构 {1=>"one",2=>"b"}


    const map2=new Map(
        [...map].map(([k,v])=>[k*2,"_"+v])
    );
    //产生map结构 {2=>"_one",4=>"_two",6=>"_three"}
    
4.forEach():遍历Map的所有成员。

Map的forEach方法与数组的forEach方法类似,可以实现遍历。

const map = new Map([
        [1, "one"],
        [2, "two"],
        [3, "three"]
    ]);

    map.forEach(function (value, key, map) {
        console.log("Key:%s,Value:%s", key, value);
    });
    // Key:1,Value:one
    // Key:2,Value:two
    // Key:3,Value:three

forEach方法还可以接受第二个参数,用于绑定this。

 const map = new Map([
        [1, "one"],
        [2, "two"],
        [3, "three"]
    ]);
    const 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:1,Value:one
    // Key:2,Value:two
    // Key:3,Value:three

(4)与其他数据结构的转化

1.Map转为数组

Map转为数组最方便的方法就是使用扩展运算符(…)(这里的例子和前面的例子相同)

 const map = new Map([
        ["1", "one"],
        ["2", "two"],
        ["3", "three"]
    ]);

    console.log([...map.keys()]);
    //["1","2","3"]

    console.log([...map.values()]);
    //["one","two","three"]

    console.log([...map.entries()]);
    //[["1","one"],["2","two"],["3","three"]]

    console.log([...map]);
    //[["1","one"],["2","two"],["3","three"]]
    
2.数组转为Map

将数组传入构造函数就可以转为Map。

数组的成员都是双元素数组:
   const map = new Map([
        [1,"one"],
        [2, "two"],
        [3, "three"]
    ]);
//     Map{
//     1 => "one",
//     2 => "two",
//     3 => "three"
// }
数组的成员存在单元素数组:
   const map = new Map([
        [1],
        [2, "two"],
        [3, "three"]
    ]);
//     Map{
//     1 => undefined,
//     2 => "two",
//     3 => "three"
// }
数组的成员存在三个元素的数组:
   const map = new Map([
        [1"one","_one"],
        [2, "two"],
        [3, "three"]
    ]);
//     Map{
//     1 => "one",
//     2 => "two",
//     3 => "three"
// }
3.Map转为对象

如果Map的所有键都是字符串,则可以转为对象。

   function strMapToObj(strMap) {
        let obj = Object.create(null);
        for (let [k, v] of strMap) {
            obj[k] = v;
        }
        return obj;
    }

    const myMap = new Map()
        .set('yes', true)
        .set('no', false)
    let a = strMapToObj(myMap);

    console.log(a)
    // { yes: true, no: false }
4.对象转为Map
   function objToStrMap(obj) {
        let strMap = new Map();
        for (let k of Object.keys(obj)) {
            strMap.set(k, obj[k]);
        }
        return strMap;
    }

    let a=objToStrMap({yes: true, no: false});

    console.log(a)
    // Map {"yes" => true, "no" => false}
5.Map转为JSON
Map的键名都是字符串:

将Map转为对象,之后调用JSON.stringify()转化为对象JSON:

function strMapToJson(strMap) {
  return JSON.stringify(strMapToObj(strMap));
}

let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
Map的键名存在非字符串:

将Map转为数组,之后调用JSON.stringify()转化为数组JSON:

function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}

let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
6.JSON转为Map
对象JSON(所有键名都是字符串)转为Map:

调用JSON.parse()将对象JSON(所有键名都是字符串)转为对象,之后将对象转为Map。

function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}

jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}
数组JSON(每个数组成员本身是一个具有两个成员的数组)转为Map:

调用JSON.parse()将数组JSON转为数组,之后将数组传入Map的构造函数。

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
}

jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}

数组成员存在三个元素的数组,则忽略第三个元素:

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
}

jsonToMap('[[true,7,8],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}

数组成员存在单元素的数组:

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
}

jsonToMap('[[true],[{"foo":3},["abc"]]]')
// Map {true => undefined, Object {foo: 3} => ['abc']}

参考文献:《ECMAScript 6 入门》阮一峰

你可能感兴趣的:(ES6)