ES6标准入门 第3版 读书笔记之Set和Map 数据结构

一:Set

  • ES6提供了新的数据结构Set。它类似于数组,但是成员的值是唯一的,没有重复的值。

  • Set是一个构造函数,用来生成Set数据结构。

  • Set加入值的时候,是不会发生类型转换,例如:5"5"是两个不同的值。注意:向Set加入值时,NaN等于自身。

Set实例的属性和方法

属性:

  • Set.prototype.constructor:构造函数,默认就是Set函数
  • Set.prototype.size:返回Set实例的成员总数

方法:

  • Set.prototype.add(value):添加某个值,返回Set结构本身
  • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功
  • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员
  • Set.prototype.clear():清除所有成员,没有返回值

注意:Array.from方法可以将Set结构转为数组(实现数组去重)

Set结构的遍历操作

有四个遍历方法,可以用于遍历成员:

  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器
  • Set.prototype.entries():返回键值对的遍历器
  • Set.prototype.forEach():使用回调函数遍历每个成员

注意:

  1. Set的遍历顺序就是插入的顺序。
  2. 由于Set结构没有键名,只有键值,所以keys方法和values方法的行为完全一致
  3. Set结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法
    Set.prototype[Symbol.iterator] == Set.prototype.values
    
    这表示,可以使用for...of循环遍历Set
  4. 也可以使用forEach()
    let set = new Set([1,2,3]);
    set.forEach((value,key) => console.log(key+':'+value))
    // 1
    // 2
    // 3
    
各种遍历的应用
  • 扩展运算符...
  • 数组的mapfilter方法可以间接用于Set
  • 在遍历操作中改变原来的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是一个构造函数,可以使用new命令来创建WeakSet数据结构

  • WeakSet可以接受一个数组或类似数组的对象作为参数(任何具有Iterable接口的对象,都可以作为WeakSet的参数)。该数组的所有成员,都会自动成为WeakSet实例对象的成员

    const a = [[1,2],[3,4]];
    const ws = new WeakSet(a);
    // WeakSet{[1,2],[3,4]}
    
    const b = [3,4];
    const ws = new WeakSet(b);
    // Uncaught TypeError: Invalid value used in weak set(…)
    

注意:是a数组的成员为WeakSet的成员,而不是a数组本身。意味着,数组的成员只能是对象。

WeakSet结构有以下三个方法:

  • WeakSet.prototype.add(value):向WeakSet实例添加一个新成员
  • WeakSet.prototype.delete(value):清除WeakSet实例的指定成员
  • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在WeakSet实例之中

注意:

  • WeakSet没有size属性,没有办法遍历它的成员
    WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在。WeakSet的一个用处,是存储DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
    const foos = new WeakSet()
    class Foo{
    	constructor(){
    		foods.add(this)
    	}
    	method(){
    		if(!foos.has(this)){
    			throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!')
    		}
    	}
    }
    
    这里使用WeakSet的好处:foos对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos,也不会出现内存泄漏

三:Map

  • ES6提供了Map数据结构,它类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
  • Object提供了字符串-值的对应,但是Map结构提供了值-值的对应,是一种更完善的Hash结构实现。
  • Map可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
    const map = new Map([
    	['name','小白'],
    	['title','小红']
    ]);
    map.size  // 2
    map.has('name') // true
    map.get('name') // "小白"
    map.has('title') // true
    map.get('title') // "小红"
    
    Map构造函数接受数组作为参数,实际山执行的是下面的算法:
    const items = [
    	['name','小白'],
    	['title','小红']
    ];
    const map = new Map();
    items.forEach(
    	([key,value]) => map.set(key,value)
    );
    
  • 任何具有Iterator接口,且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数。也就是说SetMap都是可以用来生成新的Map
  • 如果对同一个键多次赋值,后值会覆盖前值

注意:

  • 只有对同一个对象的引用,Map结构才将其视为同一个键。
    const map = new Map();
    map.set(['a'],123);
    map.get(['a']);  // undefined
    
    上述,实际上是俩个不同的数组实例,内存地址不一致。
    Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键(解决了同名属性碰撞的问题)
  • 如果Map的键是一个简单类型的值(数字,字符串,布尔值),只要两个值严格相等,Map将其视为一个键:0-0就是一个键,虽然NaN不严格等于自身,但Map将其视为同一个键。

Map结构的属性和方法如下

  • size属性:返回Map结构的成员总数
  • Map.prototype.set(key,value)
    set方法设置键名key对应的键值为value,然后返回整个Map结构,如果key已经有值,则会被覆盖。
    set方法返回的是当前的Map对象,因此可以采用链式写法
    let map = new Map()
    	.set(1,'a')
    	.set(2,'b')
    	.set(3,'c');
    
  • Map.prototype.get(key)
    get方法读取key对应的键值,找不到则返回undefined
  • Map.prototype.has(key)
    has方法返回一个布尔值,表示某个键是否在当前的Map对象之中
  • Map.prototype.delete(key)
    delete方法删除某个键,返回true。失败,返回false
  • Map.prototype.clear()
    clear方法清除所有的成员,没有返回值

Map的遍历方法:

  • Map.prototype.keys():返回键名的遍历器
  • Map.prototype.values():返回键值得遍历器
  • Map.prototype.entries():返回所有成员的遍历器
  • Map.prototype.forEach():遍历Map的所有成员

注意:

  1. Map的遍历顺序就是插入顺序
  2. Map结构的默认遍历器接口(Symbol.iterator属性),就是entries方法
    map[Symbol.iterator] === map.entries
    
  3. Map结构转为数组结构,比较快速的方法是使用扩展运算符(...
  4. 结合数组的map方法,filter方法,可以实现Map的遍历和过滤(Map本身没有mapfilter方法)
  5. Map有一个forEach方法,于数组的forEach方法类似,也可以实现遍历

Map与其他数据结构的互相转换

  • Map转为数组
  • 数组转为Map
  • Map转为对象
  • 对象转为Map
  • Map转为JSON
  • JSON转为Map

四:WeakMap

WeakMap结构与Map结构类似,也是用于生成键值对的集合
WeakMapMap的区别有两点:

  • WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名
  • WeakMap的键名所指向的对象,不计入垃圾回收机制。
    即,一旦不再需要,WeakMap里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。
    例如:在网页的DOM元素上添加数据,就可以使用WeakMap结构,当该DOM元素被清除,其所对应的WeakMap记录就会自动被移除。
    注意:WeakMap弱引用的只是键名,而不是键值,键值依然是正常引用

WeakMapMap在API上的区别主要两个:

  • 没有遍历操作:即,没有keys(),values(),entries()方法,也没有size属性。
  • 无法清空,即,不支持clear方法。因此,WeakMap只有四个方法可用:get(),set(),has(),delete()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神小夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值