【ES6】Set和Map数据结构

[TOC]

Set集合

特性

  • Set类型的数据类似于数组,它是一种特殊的数据结构,但是它包含的没有重复的值
  • 在往Set内加入值的时候不会自动发生类型转换,5和’5’是两个不同的值,NaN是等于自身的
  • Set结构的键名就是键值

基本用法

1、创建Set数据结构

1
2
3
const items1 = new Set();
const items2 = new Set([1,2,3,4,5]);

1
2
// 去除数组的重复成员
[...new Set(array)]

2、在Set数据结构中两个对象总是不想等的,下面这种方式加人的两个对象不是指向同一个

但是,如果是下面这种方法加人对象的话是只能加入一次的,因为obj变量是只想同一个对象

1
2
3
4
const b = new Set();
const obj = {bb: 123};
b.add(obj);
b.add(obj);//两个只会加人一个

Set实例属性和方法

const set = new Set()
1.set.size:定义在Set原型上的属性,Set.prototype.size,返回Set实例成员总数
2.set.add(value):添加某个值( 可以是对象)到Set实例中,返回Set结构本身
3.set.delete(value):删除Set实例中的某个值( 可以是对象),返回一个布尔值,表示删除是否成功
4.set.has(value):查询Set实例中是否有value成员( 可以是对象),返回一个布尔值表示是否有
5.set.clear() :清除set所有成员,没有返回值

Set的遍历

1.set.keys()set.values()set.entries():Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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结构的实例是默认可遍历的

1
2
3
4
5
6
7
let set = new Set(['red', 'green', 'blue']);
for (let x of set) {
console.log(x);
}
// red
// green
// blue

2.set.forEach():Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。

1
2
3
4
5
set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9

3.扩展运算符...可以展开Set数据结构,其内部也是使用for…of循环,需要用[]包裹着

其他相关方法

1.Array.from()可以将Set结构转为数组

1
2
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);

数组去重:Array.from(new Set(arr))


WeakSet集合

WeakSet集合于Set集合类似,也是不重复的值,它们之间的区别是:

  • WeakSet的成员只能是对象,不能是其他类型的值
  • WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

创建WeakSet

1
2
const ws = new WeakSet();
ws.add({a:1});

实例方法

WeakSet 结构有以下三个方法。

  • WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
  • WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
  • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const ws = new WeakSet();
    const obj = {};
    const foo = {};
    ws.add(window);
    ws.add(obj);
    ws.has(window); // true
    ws.has(foo); // false
    ws.delete(window);
    ws.has(window); // false
  • WeakSet 没有size属性,没有办法遍历它的成员。WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。


Map集合

Map数据结构类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现.

  • 只有对同一个对象的引用,Map 结构才将其视为同一个键
  • 如果 Map 的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,才认为是同一个键。另外,undefined和null也是两个不同的键。虽然NaN不严格相等于自身,但 Map 将其视为同一个键

添加

往Map数据结构里添加元素
1.xx.set(键,值)
2.构造函数
Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。

1
2
3
4
5
const map = new Map([
['name', '张三'],
['title', 'Author']
]);
map.get('name') // "张三"

实例属性和方法

1.size属性
2.map.set(key, val)
3.map.get(key, val):读取key对应的键值,如果找不到就返回undefined

1
2
3
4
const m = new Map();
const hello = function() {console.log('hello');};
m.set(hello, 'Hello ES6!') // 键是函数
m.get(hello) // Hello ES6!

4.map.has(key):返回一个布尔值,表示某个键是否在当前Map对象之中
5.map.delete(key):删除某个键,返回true,失败则返回false
6.map.clear():清除所有成员

遍历

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

需要特别注意的是,Map 的遍历顺序就是插入顺序。

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

1.Map => 数组

1
let arr = [...map]

2.数组 => Map
将数组传入 Map 构造函数,就可以转为 Map。

1
2
3
4
5
6
7
8
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }

3.Map => 对象

1
2
3
4
5
6
let obj = Object.create(null);
for (let [k,v] of map) {
obj[k] = v;
}
return obj;
}

如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。

4.对象 => Map

1
2
3
4
let map = new Map();
for (let k of Object.keys(obj)) {
map.set(k, obj[k]);
}

5.Map => JSON
一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。

1
2
3
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}

另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON。

1
return JSON.stringify([...map]);

6.JSON => Map
所有键名都是字符串

1
2
3
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}


WeakMap

WeakMap与Map的结构类似,也是用于生成键值对的集合。WeakMap的设计目的在于,有时我们想在某个对象上面存放一些数据
WeakMap与Map区别:

  • WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。
  • WeakMap的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

WeakMap作用:

  • DOM 节点作为键名,存储DOM节点的一些信息
  • 部署私有属性,当实例消失全局生命的WeakMap变量就消失,不会造成内存泄漏
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    const _counter = new WeakMap();
    const _action = new WeakMap();
    class Countdown {
    constructor(counter, action) {
    _counter.set(this, counter);
    _action.set(this, action);
    }
    dec() {
    let counter = _counter.get(this);
    if (counter < 1) return;
    counter--;
    _counter.set(this, counter);
    if (counter === 0) {
    _action.get(this)();
    }
    }
    }
    const c = new Countdown(2, () => console.log('DONE'));
    c.dec()
    c.dec()
    // DONE

热评文章