Map与WeakMap

Map

JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作。这给它的使用带来了很大的限制。

为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键,是一种更完善的 Hash 结构实现。

生成Map实例

const map1 = new Map()
const map2 = new Map([
  ['name', '张三'],
  ['title', 'Author']
])

Map实例的属性

  • Map.prototype.size:返回Map实例的成员总数。

四个操作方法

  • Map.prototype.set(key,value):设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
  • Map.prototype.get(key):读取key对应的键值,如果找不到key,返回undefined
  • Map.prototype.has(key):返回一个布尔值,表示某个键是否在当前 Map 对象之中。
  • Map.prototype.delete(key):删除某个键,返回true。如果删除失败,返回false
  • Map.prototype.clear():清除所有成员,没有返回值。

四个遍历方法

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

应用

  • 扩展对象
    • 当我们有一系列对象,想记录每个对象一种属性,这时候就可以使用Map扩展对象
	let notebook = new Map();
	chickenList.forEach(function(chicken, index){
		notebook.set(chicken, getWeight(chicken));
	});

避免修改了原有对象,可能导致意外的行为
避免对象冻结了或者有不可覆盖的属性
避免与对象原有属性冲突
避免无法精准地对比到是哪一个对象

  • 完善私有属性的实现

之前的Symbol实现的私有属性的版本里,仍然存在着可以被特殊api遍历的缺陷。

基于Map的解决思路:用一个闭包内的Map来扩展每个生成的对象

let Person = (function() {
  let map = new Map()

  function Person(name,age) {
  	let prvateProperty = {
  		name:name,
  		age:age
  	}
    map.set(this,prvateProperty )
  }

  Person.prototype.getName = function() {
    return map.get(this).name
  }
  Person.prototype.age= function() {
    return map.get(this).age
  }

  return Person;
}());

WeakMap

WeakSet 类似,WeakMapMap 有两个区别。

  • WeakMap的键只能是对象,而不能是其他类型的
  • WeakMap 中对键的引用是弱引用

同样地,WeakMap 不能遍历,是因为成员都是弱引用,随时可能消失。

WeakMap只有四个方法可用:get()set()has()delete()

注意:WeakMap 弱引用的只是键名,而不是键值键值依然是正常引用。

const wm = new WeakMap();
let key = {};
let obj = {foo: 1};

wm.set(key, obj);
obj = null;
wm.get(key)
  • 完善私有属性的实现

前面基于Map的实现还存在一个问题:
当Person实例的外部引用消除时,闭包中的Map仍然有Person实例作为键的引用,Person实例不会被垃圾回收,必须等到所有的Person实例的外部引用消除,Map所在的闭包也会消除,最后Person实例才会被垃圾回收

let Person = (function() {
  let wm = new WeakMap()

  function Person(name,age) {
  	let prvateProperty = {
  		name:name,
  		age:age
  	}
    wm.set(this,prvateProperty )
  }

  Person.prototype.getName = function() {
    return wm.get(this).name
  }
  Person.prototype.age= function() {
    return wm.get(this).age
  }

  return Person;
}());
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值