Set
Set
结构的成员值是没用重复的,每个值都是唯一的。
Set本身就是一个构造函数,可以理解为一个类,使用的时候要用new
来创建一个实例。
let s = new Set();
console.log(s); // Set{}
Set
结构会自动忽略相同的值,只会保留一个相同的值。
let s = new Set();
s.add(1);
s.add(1);
console.log(s); // Set{1}
Set 实例的属性及方法
属性
size
:返回Set实例的成员总数。
let s = new Set([1,2,3,4]);
s.size; // 4
操作方法(用于操作数据)
add(value)
:添加某个值,返回 Set 结构本身。
let s = new Set();
s.add(1); // Set(1){1}
delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。
let s = new Set([1,2,3]);
s.delete(1); // true
s.delete(4); //false
console.log(s); // Set {2,3}
has(value)
:返回一个布尔值,表示该值是否为Set的成员。
let s = new Set([1,2,3,4]);
s.has(1); // true
s.has(5); // false
clear()
:清除所有成员,没有返回值。
let s = new Set([1,2,3,4]);
s.clear();
console.log(s); // Set{}
遍历方法(用于遍历成员)
keys()
:返回键名的遍历器
let s = new Set(['a','b','c']);
s.keys(); // SetIterator {"a", "b", "c"}
values()
:返回键值的遍历器
let s = new Set(['a','b','c']);
s.values(); // SetIterator {"a", "b", "c"}
entries()
:返回键值对的遍历器
let s = new Set(['a','b','c']);
s.entries(); // SetIterator {"a" => "a", "b" => "b", "c" => "c"}
forEach()
:使用回调函数遍历每个成员
let s = new Set(['a','b','c']);
s.forEach(function(v,k){
console.log(v,k);
// a a
// b b
// c c
})
Set 数组去重
let arr = [1,1,2,3,4,4,5,6,6,7,8,9,9]
let newArr = Array.from(new Set(arr)); // [1,2,3,4,5,6,7,8,9]
let newArr2 = [...new Set(arr)]; // [1,2,3,4,5,6,7,8,9]
WeakSet
WeakSet
结构与 Set 类似,也是不重复的值的集合。
WeakSet 的成员必须是对象类型
let ws = new WeakSet([1,2]); // 报错
let ws2 = new WeakSet([{'a':11}]); // WeakSet{Object {a:11}}
- 作为构造函数,WeakSet 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。
let a = [[1, 2], [3, 4]];
let ws = new WeakSet(a);
// WeakSet {[1, 2], [3, 4]}
WeakSet结构不可遍历
- WeakSet结构也提供
add()
,delete()
,has()
方法,作用与用法和Set完全一致。 - WeakSet结构的成员都是
对象的弱引用
,随时可能被回收机制回收,成员消失,So,WeakSet结构不会有keys()
,values()
,entries()
,forEach()
等方法和size属性
。
Map
Map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
let m = new Map([
["a","aaa"],
["b",222]
])
console.log(m);
// Map {"a" => "aaa", "b" => 222}
Map 实例的属性及方法
属性
size
属性返回 Map 结构的成员总数
let m = new Map();
m.set(1,2);
m.set(3,4);
m.size; // 2
操作方法(用于操作数据)
set():
给实例设置一对键值对,返回map实例
let m = new Map();
//添加一个string类型的键名
m.set("a","aaa");
//添加一个数字类型的键名
m.set(111,222);
console.log(m); // Map {"a" => "aaa",111 => 222}
注意:
如果你设置一个已经存在的键名,那么后面的键值会覆盖前面的键值
let m = new Map();
m.set("a","aaa");
console.log(m);
// Map {"a" => "aaa"}
//再次设置name的值
m.set("b","bbb");
console.log(m);
// Map {"b" => "bbb"}
Map结构确实可以存储非字符串类型的键名
let m = new Map();
//数组类型的键名
m.set([1],2);
//对象类型的键名
m.set({"name":"Zhangsan"},2);
//布尔类型的键名
m.set(true,2);
//Symbol类型的键名
m.set(Symbol('name'),2);
//null为键名
m.set(null,2);
//undefined为键名
m.set(undefined,2);
get():
获取指定键名的键值,返回键值。
let m = new Map([["a","aaa"]]);
m.get("a"); // aaa
m.get("b"); // undefined
delete():
删除指定的键值对,删除成功返回:true,否则返回:false。
let m = new Map();
m.set("a","aaa");
console.log(m); // Map {"a" => "aaa"}
m.delete("a"); // true
m.delete("b"); // false
clear():
跟Set结构一样,Map结构也提供了clear( )方法,一次性删除所有键值对
let m = new Map();
m.set("a","aaa");
m.set("b",222);
console.log(m); // Map {"a" => "aaa","b" => 222}
m.clear();
console.log(m); // Map {}
has():
判断Map实例内是否含有指定的键值对,有就返回:true,否则返回:false。
let m = new Map();
m.set("a","aaa");
m.has("a"); // true
m.has("b"); // false
遍历方法(用于遍历成员)
keys():
返回实例所有键名的遍历器。
let m = new Map([
["a","aaa"],
["b",222]
]);
for(let i of m.keys()){
console.log(i);
// a
// b
}
values():
返回实例所有键值的遍历器。
let m = new Map([
["a","aaa"],
["b",222]
]);
for(let j of m.values()){
console.log(j);
// aaa
// 222
}
entries():
返回实例的键值对遍历器
let m = new Map([
["a","aaa"],
["b",222]
]);
for(let [i,v] of m.entries()){
console.log(i,v);
// a aaa
// b 222
}
forEach():
使用回调函数遍历每个成员
let m = new Map([
["a","aaa"],
["b",222]
]);
m.forEach((v,i) => {
console.log(i,v);
// a aaa
// b 222
})
Map与其他数据结构的互相转换
Map 转 数组
let m1 = new Map()
.set("a", 1)
.set({foo: 3}, ['abc']);
[...m1]
// [ [ "a", 1 ], [ { foo: 3 }, [ 'abc' ] ] ]
数组 转 Map
new Map([
["a", 1],
[{foo: 3}, ['abc']]
])
// Map {
// a => 1,
// Object {foo: 3} => ['abc']
// }
Map 转 对象
function MapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
let myMap = new Map()
.set('a', 111)
.set('b', 222);
MapToObj(myMap)
// { a: 111, b: 222}
对象 转 Map
function objToMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToMap({a: 111, b: 222})
// Map {"a" => 111, "b" => 222}
Map 转 JSON
//1、 Map 的键名都是字符串--转为对象 JSON。
function strMapToJson(strMap) {
return JSON.stringify(MapToObj(strMap));
}
let myMap = new Map().set('a', 111).set('b', 222);
strMapToJson(myMap)
// '{"a":111,"b":222}'
//2、 Map 的键名有非字符串--转为数组 JSON
function mapToArrayJson(map) {
return JSON.stringify([...map]);
}
let myMap = new Map().set(true, 2).set({a: 1}, ['b']);
mapToArrayJson(myMap)
// '[[true,2],[{"a":1},["b"]]]'
JSON 转 Map
//1、 所有键名都是字符串。
function jsonToStrMap(jsonStr) {
return objToMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}
//2、 整个 JSON 就是一个数组,Map 转为数组 JSON 的逆操作。
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
jsonToMap('[[true,2],[{"a":1},["abc"]]]')
// Map {true => 2, Object {a: 1} => ['abc']}
WeakMap
WeakMap
结构和Map结构很类似,也是用于生成键值对的集合。
WeakMap结构的键名只支持引用类型
的数据 (null
除外)。
let wm = new WeakMap();
wm.set(1, 2)
// TypeError: 1 is not an object!
wm.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
wm.set(null, 2)
// TypeError: Invalid value used as weak map key
WeakMap的键名所指向的对象,不计入垃圾回收机制
let a1 = document.getElementById('a');
let b2 = document.getElementById('b');
let arr = [
[a1, 'a 元素'],
[b2, 'b 元素'],
];
//不需要 a1 和 b2 的时候,必须手动删除引用
arr [0] = null;
arr [1] = null;
WeakMap
是为了防止内存泄漏
而诞生的,它的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用
。
WeakMap结构不可遍历
- WeakMap结构也提供
set()
,get()
,delete()
,has()
等方法,作用与用法和Map完全一致。 - WeakMap结构的成员都是
对象的弱引用
,随时可能被回收机制回收,成员消失,So,WeakMap结构不会有keys()
,values()
,entries()
,forEach()
等方法和size属性
。