Set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 在 ES6 中的定义:
interface SetConstructor {
new <T = any>(values?: readonly T[] | null): Set<T>;
readonly prototype: Set<any>;
}
declare var Set: SetConstructor;
通过 new 创建一个 Set 集合:
const s = new Set();
const s = new Set([1, 2, 3, 4]);
Set 接受一个由任意类型的数组作为参数,一个Set集合。
interface Set<T> {
add(value: T): this;
clear(): void;
delete(value: T): boolean;
forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
has(value: T): boolean;
readonly size: number;
}
- 方法:
-
add添加某个值,返回set本身; -
clear清空set所有元素,没有返回值; -
delete删除某个值,返回一个boolean,表示删除是否成功; -
has返回一个布尔值,表示set是否有该成员;
-
- 属性:
-
size返回set实例的成员总数。
-
WeakSet
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是WeakSet 的成员只能是复杂类型的值(或继承自 object)。
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
interface WeakSetConstructor {
new <T extends object = object>(values?: readonly T[] | null): WeakSet<T>;
readonly prototype: WeakSet<object>;
}
定义一个 WeakSet:
const ws = new WeakSet();
const ws = new WeakSet([[1, 2], [3, 4]]);
ws.add(1); // TypeError: Invalid value used in weak set
WeakSet 没有 size 属性,没有办法遍历它的成员。
interface WeakSet<T extends object> {
add(value: T): this;
delete(value: T): boolean;
has(value: T): boolean;
}
WeakSet 有三个方法:
-
add向 weakset 中增加一个新成员。 -
delete清除 WeakSet 实例的指定成员。 -
has返回一个布尔值,表示某个值是否在WeakSet实例之中。
Map
interface MapConstructor {
new(): Map<any, any>;
new<K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
readonly prototype: Map<any, any>;
}
Map 类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content') // 使用o作为Map的一个键值,其value是‘content’
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
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;
}
-
Map的属性:-
size返回Map结构的成员总数。
-
-
Map的方法:-
clear清楚Map所有的成员,返回空; -
delete删除Map指定Key的成员,返回是否删除成功; -
get获取指定Key的成员的Value,没有该Key则返回undefined; -
has方法返回一个布尔值,表示某个键是否在当前Map对象之中。 -
set方法设置键名key对应的键值为value,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
-
-
Map.prototype.keys():返回键名的遍历器。 -
Map.prototype.values():返回键值的遍历器。 -
Map.prototype.entries():返回所有成员的遍历器。 -
Map.prototype.forEach():遍历 Map 的所有成员。
WeakMap
WeakMap 与 Map 类似,但是WeakMap只接受对象作为键名
interface WeakMapConstructor {
new <K extends object = object, V = any>(entries?: readonly [K, V][] | null): WeakMap<K, V>;
readonly prototype: WeakMap<object, any>;
}
WeakMap 与Map 在 API 上的区别主要是两个,一是没有遍历操作(即没有keys()、values()和entries()方法),也没有size属性。
interface WeakMap<K extends object, V> {
delete(key: K): boolean;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
}
-
delete删除Map指定Key的成员,返回是否删除成功; -
get获取指定Key的成员的Value,没有该Key则返回undefined; -
has方法返回一个布尔值,表示某个键是否在当前Map对象之中。 -
set方法设置键名key对应的键值为value,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
Map 与其他值的互相转换:
-
Map => Array: 使用扩展运算符
...const m = new Map().set(true, 7).set({foo: 3}, ['abc']); [...m] // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ] Array => Map: 将数组传入 Map 构造函数,就可以转为 Map。
-
Map => Object:如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
function mapToObj(m) { let obj = Object.create(null); for (let [k,v] of m) { obj[k] = v } return obj } const myMap = new Map() .set('yes', true) .set('no', false); console.log(mapToObj(myMap)); // { yes: true, no: false } -
Object => Map:
let obj = {"a":1, "b":2}; let map = new Map(Object.entries(obj)); -
Map => JSON:
-
Key 都为 字符串
function strMapToJson(strMap) { return JSON.stringify(strMapToObj(strMap)); } let myMap = new Map().set('yes', true).set('no', false); strMapToJson(myMap) // '{"yes":true,"no":false}' -
Key 为其他值
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:
function jsonToStrMap(jsonStr) { return objToStrMap(JSON.parse(jsonStr)); } jsonToStrMap('{"yes": true, "no": false}')