Weak Map与闭包Object模拟类私有属性的优势差异解析
Weak Map 对比 Object 实现类私有属性的优势
Google Apps Script 目前不支持类的私有属性,不少技术方案会用Weak Map 结合闭包来模拟这一特性,同时也有用普通 Object 实现类似效果的写法。下面先看两种实现的代码、测试逻辑及输出,再具体分析 Weak Map 的核心优势。
两种实现代码
1. Weak Map 实现方式
const myPrivate1 = (() => { const _private = new WeakMap(); class myPrivate1{ constructor({key, value}={}) { let obj = {}; obj[key] = value; _private.set(this, obj); } getPrivate(key) { return _private.get(this)[key] } setPrivate({key, value}) { let priv_attrs = _private.get(this) priv_attrs[key] = value; _private.set(this, priv_attrs); } } return myPrivate1 })()
2. Object 实现方式
const myPrivate2 = (() => { const _private = new Object(); class myPrivate2{ constructor({key, value}={}) { _private[key] = value; } getPrivate(key) { return _private[key] } setPrivate({key, value}) { _private[key] = value; } } return myPrivate2 })()
测试代码及输出
测试代码
const testPrivate = () => { const testObj1 = new myPrivate1({key: 'id', value: 'xyz123'}); const testObj2 = new myPrivate2({key: 'id', value: 'xyz123'}); testObj1.setPrivate({key: 'name', value: 'Larry'}); testObj2.setPrivate({key: 'name', value: 'Larry'}) console.log(testObj1.getPrivate('name')); console.log(testObj2.getPrivate('name')); testObj1.setPrivate({key: 'id', value: 'abc987'}); console.log(testObj1.getPrivate('id')); console.log(testObj2.getPrivate('id')); console.log(testObj1._private); console.log(testObj2._private); }
测试输出
2:40:50 PM Info Larry 2:40:50 PM Info Larry 2:40:50 PM Info abc987 2:40:50 PM Info xyz123 2:40:50 PM Info undefined 2:40:50 PM Info undefined
Weak Map 相比 Object 的核心优势
1. 实例隔离彻底,避免属性冲突
从测试输出能直接看出:修改testObj1的id属性后,testObj2的id仍保留初始值xyz123;而用 Object 实现的myPrivate2,所有实例共享同一个_private对象的键值对——只要两个实例用了相同的key,后设置的值会直接覆盖前一个的。
Weak Map 是把类实例对象本身作为键来存储私有属性,每个实例对应独立的私有属性对象,完全不会出现不同实例间的属性冲突问题。而 Object 实现本质是用字符串/符号作为键,键名重复就会互相干扰。
2. 自动内存回收,避免内存泄漏
Weak Map 的键是弱引用:当某个类实例不再被其他地方引用时,垃圾回收机制会自动回收这个实例对应的 Weak Map 条目,不会因为_private的引用导致实例无法被回收。
但用普通 Object 存储的话,即使实例被销毁,_private对象里的键值对依然会保留,除非手动删除,否则会一直占用内存,长期运行容易造成内存泄漏。
3. 键的类型限制更安全
Weak Map 只允许用对象类型作为键,刚好匹配我们用类实例作为标识的场景,不会出现用字符串等原始类型作为键导致的冲突风险。而 Object 的键会自动把非字符串/符号类型转为字符串,进一步增加了冲突概率。
内容的提问来源于stack exchange,提问作者Larry Berrill
相关产品推荐
相关产品推荐

