set
set
类似于数组,但是没有重复的值。
方法
Set.prototype.add(value)
:添加某个值,返回 Set 结构本身。Set.prototype.delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。Set.prototype.has(value)
:返回一个布尔值,表示该值是否为Set
的成员。Set.prototype.clear()
:清除所有成员,没有返回值。
注意:set加入值的时候,不会发生类型转换。另外,加入NaN
的时候,认为等于自身。两个对象总是不相等的。
遍历操作
-
Set.prototype.keys()
:返回键名的遍历器 -
Set.prototype.values()
:返回键值的遍历器 -
Set.prototype.entries()
:返回键值对的遍历器 -
Set.prototype.forEach()
:使用回调函数遍历每个成员
利用遍历实现交集、并集和差集:
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
在遍历操作中同步改变set结构有以下两种方法:
// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6
// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6
WeakSet
weakset和set类似,有两个主要区别:
weakset的成员只能是对象
weakset中的对象是弱引用,如果其他对象不引用该对象,垃圾回收机制会自动回收对象所占的内存。因此,weakset的成员不适用于引用,也不可遍历。
方法
-
WeakSet.prototype.add(value)
:向 WeakSet 实例添加一个新成员。 -
WeakSet.prototype.delete(value)
:清除 WeakSet 实例的指定成员。 -
WeakSet.prototype.has(value)
:返回一个布尔值,表示某个值是否在 WeakSet 实例之中。
const a = [[1, 2], [3, 4]];
const ws = new WeakSet(a);
// WeakSet {[1, 2], [3, 4]}
注意:weakset可以接受一个数组或类似数组的对象作为参数,但是成为weakset成员的是数组的成员而不是数组本身,所以数组的成员只能是对象
weakset的一个用处是存储DOM节点,不用担心这些节点移除的时候会发生内存泄漏。
Map
作用:解决了对象只能用字符串作为键值的问题
用法:Map可接受一个数组作为参数,数组中的元素是一个表示键值对的数组。
注意:Map的键实际上是与内存地址绑定的,内存地址不一样的两个值就视为两个键。如果两个值严格相等就视为一个键
属性和方法
-
size属性
size
属性返回map结构的成员总数 -
Map.prototype.set(key, value)
set方法返回当前map对象。设置方法如下:
const m = new Map(); m.set('edition', 6) // 键是字符串 m.set(262, 'standard') // 键是数值 m.set(undefined, 'nah') // 键是 undefined
可以更改value的值,为key重新赋值
另外,可以采取链式写法
let map = new Map() .set(1, 'a') .set(2, 'b') .set(3, 'c');
-
Map.prototype.get(key)
该方法用于读取key对应的键值,如果找不到key,则返回undefined
-
Map.prototype.has(key)
用于判断一个key是否在map对象中,返回一个布尔值
-
Map.prototype.delete(key)
用于删除一个键,成功返回true
-
Map.prototype.clear()
用于清除所有成员
遍历方法
-
Map.prototype.keys()
:返回键名的遍历器。 -
Map.prototype.values()
:返回键值的遍历器。 -
Map.prototype.entries()
:返回所有成员的遍历器。 -
Map.prototype.forEach()
:遍历 Map 的所有成员。
用法如下:
for (let key of map.keys()) {
console.log(key);
}
for (let value of map.values()) {
console.log(value);
}
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
除此之外,还可以用数组的map方法、foreach方法和filter方法,可以实现map的遍历和过滤,用法如下:
const map0 = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
const map1 = new Map(
[...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}
const map2 = new Map(
[...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}
与其他数据结构互相转换
-
Map转成数组
最简便的方法就是使用扩展运算符
...
-
数组转成Map
将数组传入构造函数就可以实现:
new Map([ [true, 7], [{foo: 3}, ['abc']] ])
-
Map转成对象
function strMapToObj(strMap) { let obj = Object.create(null); for (let [k,v] of strMap) { obj[k] = v; } return obj; } const myMap = new Map() .set('yes', true) .set('no', false); strMapToObj(myMap) // { yes: true, no: false }
直接遍历再将键值插入对象中就好了。
如果键不是字符串,会将键名转换成字符串,再作为对象键名。
-
对象转成Map
遍历对象中的元素,再用set方法加入map中
-
Map转成JSON
键名都是字符串,可以先将Map转成对象,再转成JSON格式
-
键名有非字符串,可以转成数组JSON
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
先转成对象再转成JSON
-
如果JSON是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。
function jsonToMap(jsonStr) { return new Map(JSON.parse(jsonStr)); } jsonToMap('[[true,7],[{"foo":3},["abc"]]]') // Map {true => 7, Object {foo: 3} => ['abc']}
WeakMap
与Map的区别:
WeakMap只接受对象作为键名(null除外)
WeakMap的键名所指向的对象,不计入垃圾回收机制
语法:
- 与Map相比没有遍历操作,没有size属性
- 四个方法:
set()
get()
has()
delete()