set和map数据结构学习笔记

set

set类似于数组,但是没有重复的值。

方法

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

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

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

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

注意:set加入值的时候,不会发生类型转换。另外,加入NaN的时候,认为等于自身。两个对象总是不相等的。

遍历操作

  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器
  • Set.prototype.entries():返回键值对的遍历器
  • Set.prototype.forEach():使用回调函数遍历每个成员

利用遍历实现交集、并集和差集:

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}

在遍历操作中同步改变set结构有以下两种方法:

// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6

// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6

WeakSet

weakset和set类似,有两个主要区别:

  • weakset的成员只能是对象

  • weakset中的对象是弱引用,如果其他对象不引用该对象,垃圾回收机制会自动回收对象所占的内存。因此,weakset的成员不适用于引用,也不可遍历。

方法

  • WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
  • WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
  • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。
const a = [[1, 2], [3, 4]];
const ws = new WeakSet(a);
// WeakSet {[1, 2], [3, 4]}

注意:weakset可以接受一个数组或类似数组的对象作为参数,但是成为weakset成员的是数组的成员而不是数组本身,所以数组的成员只能是对象

weakset的一个用处是存储DOM节点,不用担心这些节点移除的时候会发生内存泄漏。

Map

作用:解决了对象只能用字符串作为键值的问题

用法:Map可接受一个数组作为参数,数组中的元素是一个表示键值对的数组。

注意:Map的键实际上是与内存地址绑定的,内存地址不一样的两个值就视为两个键。如果两个值严格相等就视为一个键

属性和方法

  • size属性

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

  • Map.prototype.set(key, value)

    set方法返回当前map对象。设置方法如下:

    const m = new Map();
    
    m.set('edition', 6)        // 键是字符串
    m.set(262, 'standard')     // 键是数值
    m.set(undefined, 'nah')    // 键是 undefined
    
    

    可以更改value的值,为key重新赋值

    另外,可以采取链式写法

    let map = new Map()
      .set(1, 'a')
      .set(2, 'b')
      .set(3, 'c');
    
    
  • Map.prototype.get(key)

    该方法用于读取key对应的键值,如果找不到key,则返回undefined

  • Map.prototype.has(key)

    用于判断一个key是否在map对象中,返回一个布尔值

  • Map.prototype.delete(key)

    用于删除一个键,成功返回true

  • Map.prototype.clear()

    用于清除所有成员

遍历方法

  • Map.prototype.keys():返回键名的遍历器。
  • Map.prototype.values():返回键值的遍历器。
  • Map.prototype.entries():返回所有成员的遍历器。
  • Map.prototype.forEach():遍历 Map 的所有成员。

用法如下:

for (let key of map.keys()) {
  console.log(key);
}

for (let value of map.values()) {
  console.log(value);
}

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}

除此之外,还可以用数组的map方法、foreach方法和filter方法,可以实现map的遍历和过滤,用法如下:

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'}

与其他数据结构互相转换

  • Map转成数组

    最简便的方法就是使用扩展运算符...

  • 数组转成Map

    将数组传入构造函数就可以实现:

    new Map([
      [true, 7],
      [{foo: 3}, ['abc']]
    ])
    
    
  • 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);
    strMapToObj(myMap)
    // { yes: true, no: false }
    
    

    直接遍历再将键值插入对象中就好了。

    如果键不是字符串,会将键名转换成字符串,再作为对象键名。

  • 对象转成Map

    遍历对象中的元素,再用set方法加入map中

  • Map转成JSON

    • 键名都是字符串,可以先将Map转成对象,再转成JSON格式

    • 键名有非字符串,可以转成数组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

    • 先转成对象再转成JSON

    • 如果JSON是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。

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

WeakMap

与Map的区别:

  • WeakMap只接受对象作为键名(null除外)

  • WeakMap的键名所指向的对象,不计入垃圾回收机制

语法:

  • 与Map相比没有遍历操作,没有size属性
  • 四个方法:
    • set()
    • get()
    • has()
    • delete()

参考资料

ECMAScript 6 入门

你可能感兴趣的:(set和map数据结构学习笔记)