zoukankan      html  css  js  c++  java
  • ES6 |Set和Map数据结构

    Set和Map数据结构

    在这里插入图片描述

    Set数据结构

    ES6 提供了新的数据结构——Set。 Set 本身是一个构造函数,用来生成 Set 数据结构

    1. 特性

    • Set成员的值都是唯一的,没有重复

      const set = new Set ([1, 2 , 3 , 4, 4]); 
      [ ...set] 
      //[1, 2 , 3 , 4]
      
    • 向Set加入值的时候,不会发生类型转换

    • Set内部判断两个值是否不同,使用的算法叫做“Same-value equality”,它类似于精确相等运算符(===

      在Set内部,两个NaN是相等

      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
      

    2. 属性与方法

    • Set.prototype.constructor:构造函数,默认就是Set函数

    • Set.prototype.size:返回Set实例的成员总数

    • add(value):添加某个值,返回Set结构本身

    • delete(value):删除某个值,返回一个布尔值,表示删除是否成功

    • has(value):返回一个布尔值,表示该值是否为Set的成员

    • clear():清除所有成员,没有返回值

      s.add(1).add(2).add(2);	//[1,2]
      s.size // 2
      s.has(1) // true
      s.has(2) // true
      s.has(3) // false
      s.delete(2);
      s.has(2) // false
      
    • keys():返回键名的遍历器

    • values():返回键值的遍历器

    • entries():返回键值对的遍历器

      //由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致
      
      let set = new Set(['red', 'green', 'blue']);
      for (let item of set.keys()) {
        console.log(item);
      }
      // red
      // green
      // blue
      
      for (let item of set.values()) {
        console.log(item);
      }
      // red
      // green
      // blue
      
      for (let item of set.entries()) {
        console.log(item);
      }
      // ["red", "red"]
      // ["green", "green"]
      // ["blue", "blue"]
      

      Set结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法

      Set.prototype[Symbol.iterator] === Set.prototype.values	// true
      
      let set = new Set(['red', 'green', 'blue']);
      for (let x of set) {
        console.log(x);
      }
      // red
      // green
      // blue
      
    • forEach():对每个成员执行某种操作,没有返回值

      let set = new Set([1, 2, 3]);
      set.forEach((value, key) => console.log(value * 2) )
      // 2
      // 4
      // 6
      

    3. 遍历的应用

    //1. 扩展运算符(扩展运算符内部使用for...of循环,所以也可以用于Set结构)
    let set = new Set(['red', 'green', 'blue']);
    let arr = [...set];		// ['red', 'green', 'blue']
    
    //2. 去除数组的重复成员
    let arr = [3, 5, 2, 2, 5, 5];
    let unique = [...new Set(arr)]	//方式1
    let unique = new Set(arr)	//方式2
    
    //3. map()和filter()
    let set = new Set([1, 2, 3]);
    set = new Set([...set].map(x => x * 2));	// 返回Set结构:{2, 4, 6}
    let set = new Set([1, 2, 3, 4, 5]);
    set = new Set([...set].filter(x => (x % 2) == 0));	// 返回Set结构:{2, 4}
    
    //4. 并集(Union)、交集(Intersect)和差集(Difference)
    let a = new Set([1, 2, 3]);
    let b = new Set([4, 3, 2]);
    
    // 并集
    let union = new Set([...a, ...b]);
    // Set {1, 2, 3, 4}
    // 交集
    let intersect = new Set([...a].filter(x => b.has(x)));
    // set {2, 3}
    // 差集
    let difference = new Set([...a].filter(x => !b.has(x)));
    // Set {1}
    
    //5. 在遍历中同步改变原来的Set结构
    //方式1:利用原Set结构映射出一个新的结构,然后赋值给原来的Set结构
    let set = new Set([1, 2, 3]);
    set = new Set([...set].map(val => val * 2));	//[2,6,4]
    
    //方式2:Array.from
    let set = new Set([1, 2, 3]);
    set = new Set(Array.from(set, val => val * 2));
    

    WeakSet

    WeakSet结构与Set类似,也是不重复的值的集合。但WeakSet的成员只能是对象,对象都是弱引用,不可遍历

    1. 特性

    • WeakSet是一个构造函数

      var ws = new WeakSet();
      
    • 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有iterable接口的对象,都可以作为WeakSet的参数。)

      var a = [[1,2], [3,4]];
      var ws = new WeakSet(a);
      
      var b = [3, 4];
      var ws = new WeakSet(b);
      // Uncaught TypeError: Invalid value used in weak set(…)
      

    2. 方法

    • WeakSet.prototype.add(value):向WeakSet实例添加一个新成员

    • WeakSet.prototype.delete(value):清除WeakSet实例的指定成员

    • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在WeakSet实例之中

      var ws = new WeakSet();
      var obj = {};
      var foo = {};
      
      ws.add(window);
      ws.add(obj);
      
      ws.has(window); // true
      ws.has(foo);    // false
      
      ws.delete(window);
      ws.has(window);    // false
      

    Map数据结构

    1. 背景

    对象(Object)本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。下面代码原意是将一个DOM节点作为对象data的键,但是由于对象只接受字符串作为键名,所以element被自动转为字符串[object HTMLDivElement]

    var data = {};
    var element = document.getElementById('myDiv');
    
    data[element] = 'metadata';
    data['[object HTMLDivElement]'] // "metadata"
    

    2. 特性

    • Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键

      var m = new Map();
      var o = {p: 'Hello World'};
      
      m.set(o, 'content')
      m.get(o) // "content"
      //解析:set方法将对象o当作m的一个键,然后又使用get方法读取这个键
      
      m.has(o) // true
      m.delete(o) // true
      m.has(o) // false
      
    • 可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组

      var map = new Map([
        ['name', '张三'],
        ['title', 'Author']
      ]);
      
      map.size // 2
      map.has('name') // true
      map.get('name') // "张三"
      map.has('title') // true
      map.get('title') // "Author"
      
    • 如果对同一个键多次赋值,后面的值将覆盖前面的值

      let map = new Map();
      map.set(1, 'aaa').set(1, 'bbb');
      map.get(1) // "bbb"
      
    • 只有对同一个对象的引用,Map结构才将其视为同一个键。Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键

      var map = new Map();
      map.set(['a'], 555);
      map.get(['a']) // undefined
      //解析:表面是针对同一个键,但实际上这是两个值,内存地址是不一样的
      

    3. 属性和方法

    • size:返回Map结构的成员总数

      let map = new Map();
      map.set('foo', true);
      map.set('bar', false);
      map.size // 2
      
    • set(key, value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。set方法返回的是Map本身,因此可以采用链式写法

      var m = new Map();
      m.set("edition", 6)        // 键是字符串
      m.set(262, "standard")     // 键是数值
      m.set(undefined, "nah")    // 键是undefined
      
      let map = new Map()
        .set(1, 'a')
        .set(2, 'b')
        .set(3, 'c');
      
    • get(key):读取key对应的键值,如果找不到key,返回undefined

      var m = new Map();
      var hello = function() {console.log("hello");}
      m.set(hello, "Hello ES6!") // 键是函数
      m.get(hello)  // Hello ES6!
      
    • has(key):返回一个布尔值,表示某个键是否在Map数据结构中

    • delete(key):删除某个键,返回true。如果删除失败,返回false

    • clear():清除所有成员,没有返回值


    4. 遍历的应用

    • keys():返回键名的遍历器

    • values():返回键值的遍历器

    • entries():返回所有成员的遍历器

    • forEach():遍历Map的所有成员

      let 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);
      }
      
      // 等同于使用map.entries()
      for (let [key, value] of map) {
        console.log(key, value);
      }
      
    • Map结构转为数组结构——使用扩展运算符(...

      let map = new Map([
        [1, 'one'],
        [2, 'two'],
        [3, 'three'],
      ]);
      
      [...map.keys()]		// [1, 2, 3]
      [...map.values()]	// ['one', 'two', 'three']
      [...map.entries()]	// [[1,'one'], [2, 'two'], [3, 'three']]	
      [...map]	// [[1,'one'], [2, 'two'], [3, 'three']]	
      

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

      let map0 = new Map().set(1, 'a').set(2, 'b').set(3, 'c');
      let map1 = new Map(
        [...map0].filter(([k, v]) => k < 3)
      );
      // 产生Map结构 {1 => 'a', 2 => 'b'}
      
      let map2 = new Map(
        [...map0].map(([k, v]) => [k * 2, '_' + v])
          );
      // 产生Map结构 {2 => '_a', 4 => '_b', 6 => '_c'}
      
    • forEach()

      map.forEach(function(value, key, map) {
        console.log("Key: %s, Value: %s", key, value);
      });
      

    5. 与其他数据结构的互相转换

    • Map转为数组——使用扩展运算符(...

      let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
      [...myMap]	// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
      
    • 数组转为Map——Map构造函数

      new Map([[true, 7], [{foo: 3}, ['abc']]])
      // Map {true => 7, Object {foo: 3} => ['abc']}
      
    • Map转为对象(Map的键都是字符串的情况下)

      function strMapToObj(strMap) {
        let obj = Object.create(null);
        for (let [k,v] of strMap) {
          obj[k] = v;
        }
        return obj;
      }
      
      let myMap = new Map().set('yes', true).set('no', false);
      strMapToObj(myMap)
      // { yes: true, no: false }
      
    • 对象转为Map

      function objToStrMap(obj) {
        let strMap = new Map();
        for (let k of Object.keys(obj)) {
          strMap.set(k, obj[k]);
        }
        return strMap;
      }
      
      objToStrMap({yes: true, no: false})
      // [ [ 'yes', true ], [ 'no', false ] ]
      
    • Map转为JSON

      //情况1:Map的键名都是字符串,转为对象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}'
      
      //情况2:Map的键名有非字符串,转为数组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"]]]'
      
    • JSON转为Map

      //情况1:JSON键名都是字符串
      function jsonToStrMap(jsonStr) {
        return objToStrMap(JSON.parse(jsonStr));
      }
      
      jsonToStrMap('{"yes":true,"no":false}')
      // Map {'yes' => true, 'no' => false}
      
      //情况2:JSON是一个数组
      function jsonToMap(jsonStr) {
        return new Map(JSON.parse(jsonStr));
      }
      
      jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
      // Map {true => 7, Object {foo: 3} => ['abc']}
      

    WeakMap

    1. 特性

    WeakMap结构与Map结构基本类似,但它只接受对象作为键名(null除外)没有遍历操作、没有size属性,无法清空,即不支持clear方法

    2. 方法

    • get()
    • set()
    • has()
    • delete()
  • 相关阅读:
    探寻京东云核心竞争力的源泉
    在线公开课 | 教你如何自行搭建一个威胁感知大脑?
    推迟学习系统调用
    linux中未实现的系统调用
    man(2) V
    man(2) W
    图像叠加
    man(2) readv writev
    qt 视频播放
    ffmpeg参数
  • 原文地址:https://www.cnblogs.com/sanhuamao/p/13595744.html
Copyright © 2011-2022 走看看