ES6 简单入门
主要学习 @阮一峰 的ES6电子书,梳理今后工作中可能用到的一些功能和细节
Set和Map数据结构
Set
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构。
|
|
Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
|
|
去除数组重复成员的方法
|
|
向Set加入值的时候,不会发生类型转换,所以5和”5”是两个不同的值。Set内部判断两个值是否不同,使用的算法叫做“Same-value equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。
|
|
上面代码向 Set 实例添加了两个NaN,但是只能加入一个。这表明,在 Set 内部,两个NaN是相等。
另外,两个对象总是不相等的。
|
|
上面代码表示,由于两个空对象不相等,所以它们被视为两个值。
Set 实例的属性和方法
Set 结构的实例有以下属性。
==Set.prototype.constructor==:构造函数,默认就是Set函数。
==Set.prototype.size==:返回Set实例的成员总数。
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
==add(value)==:添加某个值,返回Set结构本身。
==delete(value)==:删除某个值,返回一个布尔值,表示删除是否成功。
==has(value)==:返回一个布尔值,表示该值是否为Set的成员。
==clear()==:清除所有成员,没有返回值。
上面这些属性和方法的实例如下。
|
|
数组重复成员的另一种方法。
|
|
遍历操作
Set 结构的实例有四个遍历方法,可以用于遍历成员。
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
set=>array
|
|
array 去重操作
|
|
数组的map和filter方法也可以用于 Set(由于set是不存在重复元素,如果反过来处理就要考虑数组的元素可重复性)
|
|
使用 Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)
|
|
如果想在遍历操作中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。一种是利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构;另一种是利用Array.from方法。
|
|
WeakSet
日常使用情况不多,先记录理论,后续如果有场景再来进行补充
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别
- WeakSet 的成员只能是对象,而不能是其他类型的值
- WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中
这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为0,垃圾回收机制就不会释放这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历
Map
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
|
|
作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
|
|
Map连续赋值
如果读取一个未知的键,则返回undefined
如果 Map 的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map 将其视为一个键,比如0和-0就是一个键,布尔值true和字符串true则是两个不同的键。另外,undefined和null也是两个不同的键。虽然NaN不严格相等于自身,但 Map 将其视为同一个键。
|
|
实例的属性和操作方法
(1)size属性
(2)set(key, value)
(3)get(key)
(4)has(key)
(5)delete(key)
(6)clear()
遍历方法
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回所有成员的遍历器。
- forEach():遍历 Map 的所有成员。123456789101112131415161718192021222324252627282930313233343536const map = new Map([['F', 'no'],['T', 'yes'],]);for (let key of map.keys()) {console.log(key);}// "F"// "T"for (let value of map.values()) {console.log(value);}// "no"// "yes"for (let item of map.entries()) {console.log(item[0], item[1]);}// "F" "no"// "T" "yes"// 或者for (let [key, value] of map.entries()) {console.log(key, value);}// "F" "no"// "T" "yes"// 等同于使用map.entries()for (let [key, value] of map) {console.log(key, value);}// "F" "no"// "T" "yes"
Map 结构转为数组结构,比较快速的方法是使用扩展运算符(…)
|
|
结合数组的map方法、filter方法,可以实现 Map 的遍历和过滤(Map 本身没有map和filter方法)。
|
|
Map 还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历
|
|
forEach方法还可以接受第二个参数,用来绑定this。
上面代码中,forEach方法的回调函数的this,就指向reporter
与其他数据结构的互相转换
- Map 转为数组
Map 转为数组最方便的方法,就是使用扩展运算符(…)。
|
|
- 数组转为 Map
将数组传入 Map 构造函数,就可以转为 Map。
|
|
- Map 转为对象
如果所有 Map 的键都是字符串,它可以转为对象。
|
|
对象转为 Map
123456789function objectToMap(objcet){let map = new Map();for(let k of Object.keys(objcet)){map.set(k,objcet[k]);}return map;}const objcetO = {name: "wenyao", gender: "man", age: 28};console.log(objectToMap(objcetO));//Map(3) {"name" => "wenyao", "gender" => "man", "age" => 28}Map 转为 JSON
Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。1234567function 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。
|
|
- JSON 转为 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。
|
|
整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为Map。这往往是数组转为 JSON 的逆操作。
|
|