我有这个基于简单功能的 WeakMaps 用例/示例。
管理用户集合
我从一个User
Object 开始,它的属性包括fullname
, username
,和一个调用的方法age
,该方法打印出其他属性的人类可读摘要。gender
print
/**
Basic User Object with common properties.
*/
function User(username, fullname, age, gender) {
this.username = username;
this.fullname = fullname;
this.age = age;
this.gender = gender;
this.print = () => console.log(`${this.fullname} is a ${age} year old ${gender}`);
}
然后,我添加了一个名为 Map 的 Mapusers
来保存多个用户的集合,这些用户由username
.
/**
Collection of Users, keyed by username.
*/
var users = new Map();
添加集合还需要辅助函数来添加、获取、删除用户,甚至为了完整起见打印所有用户的函数。
/**
Creates an User Object and adds it to the users Collection.
*/
var addUser = (username, fullname, age, gender) => {
let an_user = new User(username, fullname, age, gender);
users.set(username, an_user);
}
/**
Returns an User Object associated with the given username in the Collection.
*/
var getUser = (username) => {
return users.get(username);
}
/**
Deletes an User Object associated with the given username in the Collection.
*/
var deleteUser = (username) => {
users.delete(username);
}
/**
Prints summary of all the User Objects in the Collection.
*/
var printUsers = () => {
users.forEach((user) => {
user.print();
});
}
上面的所有代码都运行在NodeJS中,只有users
Map 在整个过程中引用了用户对象。没有其他对单个用户对象的引用。
在交互式 NodeJS shell 中运行此代码,就像我添加四个用户并打印它们一样作为示例:
在不修改现有代码的情况下向用户添加更多信息
现在说需要一个新功能,其中每个用户的社交媒体平台 (SMP) 链接都需要与用户对象一起跟踪。
这里的关键还在于,必须在对现有代码的干预最少的情况下实现此功能。
这可以通过以下方式使用 WeakMaps。
我为 Twitter、Facebook、LinkedIn 添加了三个单独的 WeakMap。
/*
WeakMaps for Social Media Platforms (SMPs).
Could be replaced by a single Map which can grow
dynamically based on different SMP names . . . anyway...
*/
var sm_platform_twitter = new WeakMap();
var sm_platform_facebook = new WeakMap();
var sm_platform_linkedin = new WeakMap();
添加一个辅助函数getSMPWeakMap
只是为了返回与给定 SMP 名称关联的 WeakMap。
/**
Returns the WeakMap for the given SMP.
*/
var getSMPWeakMap = (sm_platform) => {
if(sm_platform == "Twitter") {
return sm_platform_twitter;
}
else if(sm_platform == "Facebook") {
return sm_platform_facebook;
}
else if(sm_platform == "LinkedIn") {
return sm_platform_linkedin;
}
return undefined;
}
将用户 SMP 链接添加到给定 SMP WeakMap 的函数。
/**
Adds a SMP link associated with a given User. The User must be already added to the Collection.
*/
var addUserSocialMediaLink = (username, sm_platform, sm_link) => {
let user = getUser(username);
let sm_platform_weakmap = getSMPWeakMap(sm_platform);
if(user && sm_platform_weakmap) {
sm_platform_weakmap.set(user, sm_link);
}
}
仅打印给定 SMP 上存在的用户的功能。
/**
Prints the User's fullname and corresponding SMP link of only those Users which are on the given SMP.
*/
var printSMPUsers = (sm_platform) => {
let sm_platform_weakmap = getSMPWeakMap(sm_platform);
console.log(`Users of ${sm_platform}:`)
users.forEach((user)=>{
if(sm_platform_weakmap.has(user)) {
console.log(`\t${user.fullname} : ${sm_platform_weakmap.get(user)}`)
}
});
}
您现在可以为用户添加 SMP 链接,每个用户也可以在多个 SMP 上拥有一个链接。
...继续前面的示例,我向用户添加 SMP 链接,为用户 Bill 和 Sarah 添加多个链接,然后分别打印每个 SMP 的链接:
users
现在假设通过调用从地图中删除用户deleteUser
。这删除了对用户对象的唯一引用。这反过来也会从任何/所有 SMP WeakMaps(通过垃圾收集)中清除 SMP 链接,因为没有用户对象,就无法访问其任何 SMP 链接。
...继续示例,我删除用户Bill,然后打印出与他关联的 SMP 的链接:
不需要任何额外的代码单独删除 SMP 链接,并且此功能之前的现有代码无论如何都没有修改。
如果有任何其他方法可以使用/不使用 WeakMaps 添加此功能,请随时发表评论。