javascript基础学习系列四百六十三:使用弱映射

WeakMap 实例与现有JavaScript 对象有着很大不同,可能一时不容易说清楚应该怎么使用它。这个
问题没有唯一的答案,但已经出现了很多相关策略。

  1. 私有变量
    弱映射造就了在JavaScript 中实现真正私有变量的一种新方式。前提很明确:私有变量会存储在弱
    映射中,以对象实例为键,以私有成员的字典为值。
    下面是一个示例实现:
    const wm = new WeakMap();
    class User {
    constructor(id) {
    this.idProperty = Symbol(‘id’);
    this.setId(id);
    }
    setPrivate(property, value) {
    const privateMembers = wm.get(this) || {};
    privateMembers[property] = value;
    wm.set(this, privateMembers);
    }
    getPrivate(property) {
    return wm.get(this)[property];
    }
    setId(id) {
    this.setPrivate(this.idProperty, id);
    }
    getId() {
    return this.getPrivate(this.idProperty);
    }
    }
    const user = new User(123);
    alert(user.getId()); // 123
    user.setId(456);
    alert(user.getId()); // 456
    // 并不是真正私有的
    alert(wm.get(user)[user.idProperty]); // 456
    慧眼独具的读者会发现,对于上面的实现,外部代码只需要拿到对象实例的引用和弱映射,就可以
    取得“私有”变量了。为了避免这种访问,可以用一个闭包把WeakMap 包装起来,这样就可以把弱映
    射与外界完全隔离开了:
    const User = (() => {
    const wm = new WeakMap();
    class User {
    constructor(id) {
    this.idProperty = Symbol(‘id’);
    this.setId(id);
    }
    setPrivate(property, value) {
    const privateMembers = wm.get(this) || {};
    privateMembers[property] = value;
    wm.set(this, privateMembers);
    }
    getPrivate(property) {
    return wm.get(this)[property];
    }
    setId(id) {
    this.setPrivate(this.idProperty, id);
    }
    getId(id) {
    return this.getPrivate(this.idProperty);
    }
    }
    return User;
    })();
    const user = new User(123);
    alert(user.getId()); // 123
    user.setId(456);
    alert(user.getId()); // 456
    这样,拿不到弱映射中的健,也就无法取得弱映射中对应的值。虽然这防止了前面提到的访问,但
    整个代码也完全陷入了ES6 之前的闭包私有变量模式。
  2. DOM 节点元数据
    因为WeakMap 实例不会妨碍垃圾回收,所以非常适合保存关联元数据。来看下面这个例子,其中
    使用了常规的Map:
    const m = new Map();
    const loginButton = document.querySelector(‘#login’);
    // 给这个节点关联一些元数据
    m.set(loginButton, {disabled: true});
    假设在上面的代码执行后,页面被JavaScript 改变了,原来的登录按钮从DOM 树中被删掉了。但
    由于映射中还保存着按钮的引用,所以对应的DOM 节点仍然会逗留在内存中,除非明确将其从映射中
    删除或者等到映射本身被销毁。
    如果这里使用的是弱映射,如以下代码所示,那么当节点从DOM 树中被删除后,垃圾回收程序就
    可以立即释放其内存(假设没有其他地方引用这个对象):
    const wm = new WeakMap();
    const loginButton = document.querySelector(‘#login’);
    // 给这个节点关联一些元数据
    wm.set(loginButton, {disabled: true});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值