ES6 -set-map
基本用法
ES6提供了新的数据结构Set。它类似于数组,但是成员的都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构,
Set实例的属性和方法
- Set.prototype.constructor:构造函数,默认就是Set函数
- Set.ptototype.size: 返回Set实例的成员总数
- 操作方法
- add(val) :添加某个值,返回Set结构本身
- delete(val):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为Set的成员。
- clear():清除所有成员,没有返回值。
Set.add(1).add(2).add(2) // 注意这里2被加入了两次 Set.size // 2 s.has(1) // true s.has(2) // true s.has(3) // false s.delete(2) // true s.has(2) //false
Array.from 方法可以将Set结构转为数组
const items = new Set([1,2,3,4,5]); const array = Array.from(items);
可以使用Set进行数组去重!
遍历操作
- Set结构的实例有四个遍历方法,可以用于遍历成员
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
需要特别指出的是,Set的遍历顺序就是插入顺序,这个特性有时非常有用,比我使用Set保存一个回调函数列表,调用时就能保证安装添加顺序调用
keys
方法、values
方法、entries
方法返回的都是遍历器对象,由于Set结构没有键名,只有键值,所以keys方法和values方法的行为完全一致。
entries
方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。
Set结构的实例和数组一样,也拥有forEach()方法,用于对每个成员执行某种操作,没有返回值。
WeakSet
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
WeakSet 是一个构造函数,可以使用new
命令,创建 WeakSet 数据结构。
作为构造函数,WeakSet 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。
WeakSet 结构有以下三个方法。
- WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
- WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
- WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。
Map
ES6提供了Map数据结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键,也就是说,Object结构提供了“字符串-值”的对应,Map结构提供了值-值的对应。是一种更完美的Hash结构实现,如果你需要键值对的数据结构,Map比Object更合适。
const m = new Map(); const o = {p: 'hello'}; m.set(o, 'content'); m.get(o); // content m.has(o)// true m.delete(o) // true m.has(o) // false
上面代码使用 Map 结构的set
方法,将对象o
当作m
的一个键,然后又使用get
方法读取这个键,接着使用delete
方法删除了这个键。
(1)size 属性
size
属性返回 Map 结构的成员总数。
(2)set(key, value)
set
方法设置键名key
对应的键值为value
,然后返回整个 Map 结构。如果key
已经有值,则键值会被更新,否则就新生成该键。
set
方法返回的是当前的Map
对象,因此可以采用链式写法。
(3)get(key)
get
方法读取key
对应的键值,如果找不到key
,返回undefined
。
(4)has(key)
has
方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
(5)delete(key)
delete
方法删除某个键,返回true
。如果删除失败,返回false
。
(6)clear()
clear
方法清除所有成员,没有返回值。
遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
keys()
:返回键名的遍历器。values()
:返回键值的遍历器。entries()
:返回所有成员的遍历器。forEach()
:遍历 Map 的所有成员。
需要特别注意的是,Map 的遍历顺序就是插入顺序。
(1)Map 转为数组
前面已经提过,Map 转为数组最方便的方法,就是使用扩展运算符(...
)。
const myMap = new Map() .set(true, 7) .set({foo: 3}, ['abc']); [...myMap] // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
(2)数组 转为 Map
将数组传入 Map 构造函数,就可以转为 Map。
new Map([ [true, 7], [{foo: 3}, ['abc']] ]) // Map { // true => 7, // Object {foo: 3} => ['abc'] // }
(3)Map 转为对象
如果所有 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 }
如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
(4)对象转为 Map
function objToStrMap(obj) { let strMap = new Map(); for (let k of Object.keys(obj)) { strMap.set(k, obj[k]); } return strMap; } objToStrMap({yes: true, no: false}) // Map {"yes" => true, "no" => false}
(5)Map 转为 JSON
Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。
function strMapToJson(strMap) { return JSON.stringify(strMapToObj(strMap)); } let myMap = new Map().set('yes', true).set('no', false); strMapToJson(myMap) // '{"yes":true,"no":false}'
另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 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"]]]'
(6)JSON 转为 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。
function jsonToStrMap(jsonStr) { return objToStrMap(JSON.parse(jsonStr)); } jsonToStrMap('{"yes": true, "no": false}') // Map {'yes' => true, 'no' => false}
但是,有一种特殊情况,整个 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 的语法
WeakMap 与 Map 在 API 上的区别主要是两个,一是没有遍历操作(即没有keys()
、values()
和entries()
方法),也没有size
属性。因为没有办法列出所有键名,某个键名是否存在完全不可预测,跟垃圾回收机制是否运行相关。这一刻可以取到键名,下一刻垃圾回收机制突然运行了,这个键名就没了,为了防止出现不确定性,就统一规定不能取到键名。二是无法清空,即不支持clear
方法。因此,WeakMap
只有四个方法可用:get()
、set()
、has()
、delete()
。