• 【重温基础】11.Map和Set对象


    本文是 重温基础 系列文章的第十一篇。
    今日感受:注意身体,生病花钱又难受。

    系列目录:

    本章节复习的是JS中的Map和Set对象,是个集合。

    前置知识:
    Map和Set对象是在ES6中被引入的,作为一种由key值标记的数据容器。
    Map和Set对象承载的数据元素可以按照插入时的顺序,被迭代遍历。

    1 Set对象

    介绍:
    Set数据结构类似数组,但所有成员的值唯一
    Set本身为一个构造函数,用来生成Set数据结构,使用add方法来添加新成员。

    let a = new Set();
    [1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x));
    for(let k of a){
        console.log(k)
    };
    // 1 2 3 4 5
    

    基础使用

    let a = new Set([1,2,3,3,4]);
    [...a]; // [1,2,3,4]
    a.size; // 4
    
    // 数组去重
    [...new Set([1,2,3,4,4,4])];// [1,2,3,4]
    

    注意

    • Set中添加值的时候,不会类型转换,即5'5'是不同的。
    [...new Set([5,'5'])]; // [5, "5"]
    

    属性和方法

    • 属性:

      • Set.prototype.constructor:构造函数,默认就是Set函数。
      • Set.prototype.size:返回Set实例的成员总数。
    • 操作方法:

      • add(value):添加某个值,返回 Set 结构本身。
      • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
      • has(value):返回一个布尔值,表示该值是否为Set的成员。
      • clear():清除所有成员,没有返回值。
    let a = new Set();
    a.add(1).add(2); // a => Set(2) {1, 2}
    a.has(2);        // true
    a.has(3);        // false
    a.delete(2);     // true  a => Set(1) {1}
    a.clear();       // a => Set(0) {}
    

    数组去重

    let a = new Set([1,2,3,3,3,3]);
    

    2 Set的应用

    数组去重

    // 方法1
    [...new Set([1,2,3,4,4,4])]; // [1,2,3,4]
    // 方法2
    Array.from(new Set([1,2,3,4,4,4]));    // [1,2,3,4]
    

    遍历和过滤

    let a = new Set([1,2,3,4]);
    
    // map 遍历操作
    let b = new Set([...a].map(x =>x*2));// b => Set(4) {2,4,6,8}
    
    // filter 过滤操作
    let c = new Set([...a].filter(x =>(x%2) == 0)); // b => Set(2) {2,4}
    

    获取并集、交集和差集

    let a = new Set([1,2,3]);
    let b = new Set([4,3,2]);
    
    // 并集
    let c1 = new Set([...a, ...b]);  // Set {1,2,3,4}
    
    // 交集
    let c2 = new Set([...a].filter(x => b.has(x))); // set {2,3}
    
    // 差集
    let c3 = new Set([...a].filter(x => !b.has(x))); // set {1}
    
    • 遍历方法:
      • keys():返回键名的遍历器。
      • values():返回键值的遍历器。
      • entries():返回键值对的遍历器。
      • forEach():使用回调函数遍历每个成员

    Set遍历顺序是插入顺序,当保存多个回调函数,只需按照顺序调用。但由于Set结构没有键名只有键值,所以keys()values()是返回结果相同。

    let a = new Set(['a','b','c']);
    for(let i of a.keys()){console.log(i)};   // 'a' 'b' 'c'
    for(let i of a.values()){console.log(i)}; // 'a' 'b' 'c'
    for(let i of a.entries()){console.log(i)}; 
    // ['a','a'] ['b','b'] ['c','c']
    

    并且 还可以使用for...of直接遍历Set

    let a = new Set(['a','b','c']);
    for(let k of a){console.log(k)};   // 'a' 'b' 'c'
    

    forEach与数组相同,对每个成员执行操作,且无返回值。

    let a = new Set(['a','b','c']);
    a.forEach((v,k) => console.log(k + ' : ' + v));
    

    3 Map对象

    由于传统的JavaScript对象只能用字符串当做键,给开发带来很大限制,ES6增加Map数据结构,使得各种类型的值(包括对象)都可以作为键。
    Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。
    基础使用

    let a = new Map();
    let b = {name: 'leo' };
    a.set(b,'my name'); // 添加值
    a.get(b);           // 获取值
    a.size;      // 获取总数
    a.has(b);    // 查询是否存在
    a.delete(b); // 删除一个值
    a.clear();   // 清空所有成员 无返回
    

    注意

    • 传入数组作为参数,指定键值对的数组
    let a = new Map([
        ['name','leo'],
        ['age',18]
    ])
    
    • 如果对同一个键多次赋值,后面的值将覆盖前面的值
    let a = new Map();
    a.set(1,'aaa').set(1,'bbb');
    a.get(1); // 'bbb'
    
    • 如果读取一个未知的键,则返回undefined
    new Map().get('abcdef'); // undefined
    
    • 同样的值的两个实例,在 Map 结构中被视为两个键。
    let a = new Map();
    let a1 = ['aaa'];
    let a2 = ['aaa'];
    a.set(a1,111).set(a2,222);
    a.get(a1); // 111
    a.get(a2); // 222
    

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

    • keys():返回键名的遍历器。
    • values():返回键值的遍历器。
    • entries():返回所有成员的遍历器。
    • forEach():遍历 Map 的所有成员。
    let a = new Map([
        ['name','leo'],
        ['age',18]
    ])
    
    for (let i of a.keys()){...};
    for (let i of a.values()){...};
    for (let i of a.entries()){...};
    a.forEach((v,k,m)=>{
        console.log(`key:${k},value:${v},map:${m}`)
    })
    

    将Map结构转成数组结构

    let a = new Map([
        ['name','leo'],
        ['age',18]
    ])
    
    let a1 = [...a.keys()];   // a1 => ["name", "age"]
    let a2 = [...a.values()]; // a2 =>  ["leo", 18]
    let a3 = [...a.entries()];// a3 => [['name','leo'], ['age',18]]
    

    4 Map与其他数据结构互相转换

    • Map 转 数组
    let a = new Map().set(true,1).set({f:2},['abc']);
    [...a]; // [[true:1], [ {f:2},['abc'] ]]
    
    • 数组 转 Map
    let a = [ ['name','leo'], [1, 'hi' ]]
    let b = new Map(a);
    
    • Map 转 对象
      如果所有 Map 的键都是字符串,它可以无损地转为对象。
      如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
    function fun(s) {
      let obj = Object.create(null);
      for (let [k,v] of s) {
        obj[k] = v;
      }
      return obj;
    }
    
    const a = new Map().set('yes', true).set('no', false);
    fun(a)
    // { yes: true, no: false }
    
    • 对象 转 Map
    function fun(obj) {
      let a = new Map();
      for (let k of Object.keys(obj)) {
        a.set(k, obj[k]);
      }
      return a;
    }
    
    fun({yes: true, no: false})
    // Map {"yes" => true, "no" => false}
    
    • Map 转 JSON
      (1)Map键名都是字符串,转为对象JSON:
    function fun (s) {
        let obj = Object.create(null);
        for (let [k,v] of s) {
            obj[k] = v;
        }
        return JSON.stringify(obj)
    }
    let a = new Map().set('yes', true).set('no', false);
    fun(a);
    // '{"yes":true,"no":false}'
    

    (2)Map键名有非字符串,转为数组JSON:

    function fun (map) {
      return JSON.stringify([...map]);
    }
    
    let a = new Map().set(true, 7).set({foo: 3}, ['abc']);
    fun(a)
    // '[[true,7],[{"foo":3},["abc"]]]'
    
    • JSON 转 Map
      (1)所有键名都是字符串:
    function fun (s) {
      let strMap = new Map();
      for (let k of Object.keys(s)) {
        strMap.set(k, s[k]);
      }
      return strMap;
      return JSON.parse(strMap);
    }
    fun('{"yes": true, "no": false}')
    // Map {'yes' => true, 'no' => false}
    

    (2)整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组:

    function fun2(s) {
      return new Map(JSON.parse(s));
    }
    fun2('[[true,7],[{"foo":3},["abc"]]]')
    // Map {true => 7, Object {foo: 3} => ['abc']}
    

    参考资料

    1.阮一峰ES6入门


    本部分内容到这结束

    Author 王平安
    E-mail pingan8787@qq.com
    博 客 www.pingan8787.com
    微 信 pingan8787
    每日文章推荐 https://github.com/pingan8787/Leo_Reading/issues
    JS小册 js.pingan8787.com

    bg

    个人博客:http://www.pingan8787.com 微信公众号【前端自习课】和千万网友一起,每日清晨,享受一篇前端优秀文章。 目前已连续推送文章 600+ 天,愿每个人的初心都能一直坚持下去!
  • 相关阅读:
    事件(三):事件对象
    事件(二):事件处理程序
    事件(一):事件流
    nginx里面的rewrite配置
    详解 CSS 居中布局技巧
    jQuery 效率提升建议
    web的攻击技术
    前端优化点总结
    深入理解递归和闭包
    创建对象
  • 原文地址:https://www.cnblogs.com/pingan8787/p/11838212.html
Copyright © 2020-2023  润新知