美文网首页
ES6中的Map和Set

ES6中的Map和Set

作者: 肥羊猪 | 来源:发表于2021-03-02 09:17 被阅读0次

    Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。

    // 例一
    var set = new Set([1, 2, 3, 4, 4]);
    [...set]
    // [1, 2, 3, 4]
     
    var s = new Set();
     
    [2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));
     
    for (let i of s) {
     console.log(i);
    }
    // 2 3 5 4
    
    

    注:在Set内部,两个NaN是相等。两个对象总是不相等的。可以用length来检测

    let set = new Set();
    let a = NaN;
    let b = NaN;
    set.add(a);
    set.add(b);
    set // Set {NaN}
    let set = new Set();
     
    set.add({});
    set.size // 1
    set.add({});
    set.size // 2
    
    var arr=[
        {id:1,name:'qqq'},
        {id:2,name:'qqq'},
        {id:3,name:'qqq'},
        {id:4,name:'qqq'},
        {id:2,name:'qqq'}
    ]
    const s = new Set();
    arr.forEach(x => s.add(x));
    for (let i of s) {
     console.log(i);
    }
    // {id:1,name:'qqq'},
     //   {id:2,name:'qqq'},
     //   {id:3,name:'qqq'},
      //  {id:4,name:'qqq'},
     //   {id:2,name:'qqq'},
    
    

    四个操作方法:

    add(value):添加某个值,返回Set结构本身。
    delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    has(value):返回一个布尔值,表示该值是否为Set的成员。
    clear():清除所有成员,没有返回值

    let s = new Set();
    s.add(1).add(2).add(2);
    // 注意2被加入了两次
    s.size // 2
    s.has(1) // true
    s.has(2) // true
    s.has(3) // false
     
    console.log(s.delete(2));//true
    s.has(2) // false
    
    

    set内部的元素可以遍历for...of...

    let set = new Set(['red', 'green', 'blue']);
    for (let x of set) {
     console.log(x);
    }
    // red
    // green
    // blue
    
    set = new Set([1, 4, 9]);
    set.forEach((value, key) => console.log(key + ' : ' + value))
    // 1 : 1
    // 4 : 4
    // 9 : 9
    
    
    

    Set 结构的实例有四个遍历方法,可以用于遍历成员。

    keys():返回键名的遍历器
    values():返回键值的遍历器
    entries():返回键值对的遍历器
    forEach():使用回调函数遍历每个成员
    需要特别指出的是,Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。

    Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。

    var m = new Map();
    var o = {p: "Hello World"};
     
    m.set(o, "content")
    m.get(o) // "content"
     
    m.has(o) // true
    m.delete(o) // true
    m.has(o) // false
    
    

    注意,只有对同一个对象的引用,Map结构才将其视为同一个键。这一点要非常小心。

    var map = new Map();
    map.set(['a'], 555);
    map.get(['a']) // undefined
    //set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined。
    

    注:如果Map的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map将其视为一个键,包括0和-0。另外,虽然NaN不严格相等于自身,但Map将其视为同一个键。

    实例属性和方法:size、set、get、has、delete、clear
    遍历方法:keys()、values()、entries()、forEach()

    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"
    
    

    Maps 和 Objects的区别:

    一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
    Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
    Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
    Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
    
    

    Map 的迭代:
    1.for...of

    var myMap = new Map();
    myMap.set(0, "zero");
    myMap.set(1, "one");
     
    // 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one"
    for (var [key, value] of myMap) {
      console.log(key + " = " + value);
    }
    for (var [key, value] of myMap.entries()) {
      console.log(key + " = " + value);
    }
    /* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */
     
    // 将会显示两个log。 一个是 "0" 另一个是 "1"
    for (var key of myMap.keys()) {
      console.log(key);
    }
    /* 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 */
     
    // 将会显示两个log。 一个是 "zero" 另一个是 "one"
    for (var value of myMap.values()) {
      console.log(value);
    }
    /* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */
    

    2.forEach()

    var myMap = new Map();
    myMap.set(0, "zero");
    myMap.set(1, "one");
     
    // 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one"
    myMap.forEach(function(value, key) {
      console.log(key + " = " + value);
    }, myMap)
    
    const map0 = new Map()
     .set(1, 'a')
     .set(2, 'b')
     .set(3, 'c');
     
    const map1 = new Map(
     [...map0].filter(([k, v]) => k < 3)
    );
    // 产生 Map 结构 {1 => 'a', 2 => 'b'}
     
    const map2 = new Map(
     [...map0].map(([k, v]) => [k * 2, '_' + v])
      );
    // 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}
    
    

    相互转换
    Array.from()或者扩展运算符...

    const arr = [[{'a': 1}, 111], ['b': 222]]
    const myMap = new Map(arr)
    [...myMap]//Array.from(myMap)
    
    map合并
    var first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]);
    var second = new Map([[1, 'uno'], [2, 'dos']]);
     
    // 合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的,对应值即 uno,dos, three
    var merged = new Map([...first, ...second]);
    
    set(key, val): 向Map中添加新元素
    get(key): 通过键值查找特定的数值并返回
    has(key): 判断Map对象中是否有Key所对应的值,有返回true,否则返回false
    delete(key): 通过键值从Map中移除对应的数据
    clear(): 将这个Map中的所有元素删除
    
    Map的使用.png
    Map.png

    Set
    Set对象允许你存储任何类型的值,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值。
    Set 本身是一个构造函数,用来生成Set 数据结构。Set函数可以接受一个数组(或者具有iterable接口的其他数据结构)作为参数,用来初始化。

    +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复
    undefined 与 undefined 是恒等的,所以不重复
    NaN 与 NaN 是不恒等的,但是在 Set 中认为NaN与NaN相等,所有只能存在一个,不重复。
    
    // Array 转 Set
    var mySet = new Set(["value1", "value2", "value3"]);
    // 用...操作符,将 Set 转 Array
    var myArray = [...mySet];
    
    
    add(value):添加某个值,返回 Set 结构本身(可以链式调用)。
    delete(value):删除某个值,删除成功返回true,否则返回false。
    has(value):返回一个布尔值,表示该值是否为Set的成员。
    clear():清除所有成员,没有返回值。
    
    
    Set 对象作用
    数组去重
    var mySet = new Set([1, 2, 3, 4, 4]);
    [...mySet]; // [1, 2, 3, 4]
    并集
    var a = new Set([1, 2, 3]);
    var b = new Set([4, 3, 2]);
    var union = new Set([...a, ...b]); // {1, 2, 3, 4}
    交集
    var a = new Set([1, 2, 3]);
    var b = new Set([4, 3, 2]);
    var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}
    差集
    var a = new Set([1, 2, 3]);
    var b = new Set([4, 3, 2]);
    var difference = new Set([...a].filter(x => !b.has(x))); // {1}
    
    set是一种关联式容器,其特性如下:
    
    set以RBTree作为底层容器
    所得元素的只有key没有value,value就是key
    不允许出现键值重复
    所有的元素都会被自动排序
    不能通过迭代器来改变set的值,因为set的值就是键
    map和set一样是关联式容器,它们的底层容器都是红黑树,区别就在于map的值不作为键,键和值是分开的。它的特性如下:
    
    map以RBTree作为底层容器
    所有元素都是键+值存在
    不允许键重复
    所有元素是通过键进行自动排序的
    map的键是不能修改的,但是其键对应的值是可以修改的
    

    参考https://www.runoob.com/w3cnote/es6-map-set.html

    相关文章

      网友评论

          本文标题:ES6中的Map和Set

          本文链接:https://www.haomeiwen.com/subject/brxufltx.html