javascript新增加的数据结构: Set Map WeakSet WeakMap

一、Set

ES6提供新的数据结构Set,类似于Array,不过Array中的值可以重复,但是Set中的值不可以重复

声明: Set函数是一个构造函数  

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

console.log((new Set([1,2,3,2])).size) // 3
console.log((new Set([NaN, NaN])).size) // 1
console.log((new Set([{}, {}])).size) // 2
console.log((new Set([{a: 'a'}, {a: 'a'}])).size) //2
a = {a: 'a'}
console.log((new Set([a, a])).size) // 1
b = {a: 'a'}
console.log((new Set([a, b])).size) //2
Set数据结构判断相等的方式与===类似,但是优化了NaN的判断(这里可以原来判断NaN)
Set数据结构的属性:
Set.prototype.constructor: 构造函数,默认为Set函数,new Set([1]).constructor === Set // true
Set.prototype.size: 返回Set实例的成员总数。
Set数据结构的方法
1 interface Set<T> {
2     add(value: T): this; // 增加值,返回Set实例本身,可以连调 new Set().add({}).add({})
3     clear(): void; // 清除所有值
4     delete(value: T): boolean; // 删除值,删除成功返回true
5     forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void; // 遍历Set,接受回调函数和this对象,回调函数的参数有3个,值,键,set本身,Set数据结构中没有键,所以键===值,
6     has(value: T): boolean; // value是否在Set中
7     readonly size: number; // 返回Set的成员数量
8 }

因为Set是实现了遍历器接口,所以有如下方法

keys 返回键组成的遍历器

values 返回值组成的遍历器

entries 返回键值对组成的遍历器
 
Set与数组的区别
Array Set都实现了遍历器
Array中的值可以重复,但是Set中的值不可以重复
Array中有键(0,1,2),遍历可以使用arr[0]
Set中只有值,没有键,遍历可以使用forEach, for of

Set的遍历

可以直接使用for of进行遍历

Set的应用

1 // 数组去重复(基本数据类型)
2 console.log(Array.from(new Set([1,2,1]))) // [1, 2]
3 console.log([...new Set([1,2,1])]) // [1, 2]
4 
5 a = [1, 2, 3]
6 b = [4, 3, 2]
7 // 数组并集
8 console.log([...new Set([...a, ...b])]) // [ 1, 2, 3, 4 ]

二、WeakSet

与Set的区别:

  1. WeakSet中的成员只能是对象,Set可以是任何类型
  2. WeakSet中的对象都是弱引用。垃圾回收是不会考虑对象在不在WeakSet中,所以WeakSet是不可引用的,是不能遍历的

 添加进WeakSet的元素对象,WeakSet不会对元素对像的引用计数加1,对于被添加进WeakSet的元素对象,只要该元素对象没有被除WeakSet以外的其他对象引用,就会被垃圾回收释放,在WeakSet中的该元素对象自动被释放,不会出现内存泄漏。

1 var ws = new WeakSet();
2 var foo = {};
3 ws.add(foo);
4 console.log(ws.has(foo)) // true
5 ws.delete(foo);
6 console.log(ws.has(foo)) //false
interface WeakSet<T extends object> {
    add(value: T): this;
    delete(value: T): boolean;
    has(value: T): boolean;
}

 

WeakSet的一个用法是存触DOM节点,而不用担心这些节点从文档移除时发生内存泄露。

 1 class Foo {
 2     constructor() {
 3         ws.add(this);
 4     }
 5     method() {
 6         if(!ws.has(this))  {
 7             throw new TypeError('method只能在实例中使用')
 8         }
 9     }
10 }

 

 保证Foo的实例方法只能在Foo的实例上调用。

三、Map

Object是字符串-值结构,它的键必须是字符串。

Map是值-值,它的键可以是任何类型的。

如果需要键值对的数据结构,Map更加合适。

let a = new Map([['name', 'wt'], ['age', 25]]) 构造函数,接受数组作为参数
interface Map<K, V> {
    clear(): void;
    delete(key: K): boolean;
    forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
    get(key: K): V | undefined;
    has(key: K): boolean;
    set(key: K, value: V): this;
    readonly size: number;
}

 

四、WeakMap

WeakMap与Map基本相同,不过WeakMap的键必须是对象,并且是对象的弱引用。(垃圾回收机制不考虑是否在WeakMap中)

WeakMap专门用来在它的键对应的对象可能在将来会消失。有助于防止内存泄露。

1 let a = ['name', 'wt']
2 let m = new Map().set(a, 'mmm')
3 console.log(m.get(a)) // mmm
4 a = null;
5 console.log(m.get(a)) // undefined

参考:《ES6标准入门》

posted on 2019-02-20 22:54  西门本不吹雪  阅读(216)  评论(0编辑  收藏  举报