【重学前端】ECMAScript6 - Set和Map数据结构

91 阅读3分钟

Set和Map数据结构

Set

Set可以用于去重,Set是一个构造函数,接收一个参数,这个参数是具有iterable接口的数据,比如数组,字符串,返回一个Set类型对象。

const set = new Set([1,2,3,4,4]);
const strSet = new Set('abcccd');
console.log([...set]); // [1, 2, 3, 4]
console.log([...strSet]); // ['a', 'b', 'c', 'd']

经典的数组去重方式:

Array.from(new Set(array))

属性

Set.prorotype.size返回Set实例的成员总数。

const set = new Set([1,2,3,4,4]);
console.log(set.size); // 4 去重后的数量

方法

  • add(value):添加某个值,返回Set结构本身
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功
  • has(value):返回一个布尔值,表示是否有某个值
  • clear():清除所有成员,没有返回值
  • keys():返回键名的迭代器,因为Set只有值,所以就是返回键值的迭代器
  • values():返回键值的迭代器
  • entries():返回键值对的迭代器
  • forEach()
const set = new Set([1,2,3,4,4]);
console.log(set.keys()); // SetIterator {1, 2, 3, 4}

WeakSet

WeakSet也是不重复值的集合,但它的成员值只能是对象。同时WeakSet不可遍历,因为WeakSet中的对象都是弱引用,其内部有多少个成员取决于垃圾回收机制有没有运行,运行前后成员个数不确定。

const set = new WeakSet([1,2,3,4,4]); // Uncaught TypeError: Invalid value used in weak set

const set = new WeakSet([[1],[1],[2]]);
console.log(set); // WeakSet {[1],[1],[2]}

方法

WeakSet没有size属性,也没有clear()方法,也没有用于遍历的方法。

  • add(value)
  • delete(value)
  • has(value)

Map

Map是比对象更完善的键值对结构,它的键接收各种类型的值,而且添加的key有顺序。

let num = 1;
let str = 'string';
let bool = true;
let symbol = Symbol('symbol');
let obj = {};
let value = 'hello world';

const map = new Map();
map.set(num, value);
map.set(str, value);
map.set(bool, value);
map.set(symbol, value);
map.set(obj, value);

console.log(map); // Map(5) {1 => 'hello world', 'string' => 'hello world', true => 'hello world', Symbol(symbol) => 'hello world', {…} => 'hello world'}
console.log(map.keys()); // MapIterator {1, 'string', true, Symbol(symbol), {…}}

我们知道,SetWeakSet接收的是一个数组或者说是一个具有迭代器属性的对象,而Map构造函数则接收一个键值对的数组。

let map = new Map([
    ['key1', 'value1'],
    ['key2', 'value2']
]);
console.log(map); // Map(2) {'key1' => 'value1', 'key2' => 'value2'}

let set = new Set([1,2]);
let map2 = new Map(set.entries());
console.log(map2); // Map(2) {1 => 1, 2 => 2}

对象和Map对象如何互转?

// 对所有键都是字符串的Map对象比较有用
function map2Obj(map) {
    const entries = map.entries();
    const obj = Object.create(null);
    for(let [key, value] of entries) {
        Reflect.set(obj, key, value);
    }
    return obj;
}

// 或者 return new Map(Object.entries(obj))
function obj2map(obj) {
    const map = new Map();
    Object.keys(obj).forEach((key) => {
        map.set(key, obj[key]);
    });
    return map;
}

let map = new Map([
    ['key1', 'value1'],
    ['key2', 'value2']
]);
let obj = map2Obj(map);
console.log(obj); // {key1: 'value1', key2: 'value2'}
let newMap = obj2map(obj);
console.log(newMap); // Map(2) {'key1' => 'value1', 'key2' => 'value2'}

属性

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

方法

Set对象的方法相似,触类旁通。

  • set(key, value)
  • get(key)
  • has(key)
  • delete(key)
  • clear()
  • keys()
  • values()
  • entries()
  • forEach()

WeakMap

WeakSet只能接收对象作为成员类似,WeakMap只能接收对象作为键名(null除外),同样WeakMap的键名所引用的对象都是弱引用。即一旦这个对象不在被引用,不再需要了,WeakMap里的这个键名对象和所对应键值自动消失,无需手动删除引用。

方法

同样WeakMap没有size属性,没有clear()方法和遍历的方法。

  • get(key)
  • set(key, value)
  • has(key)
  • delete(key)

参考