原型上不可挂可变对象,应将状态移至实例或用weakmap隔离;需清理闭包引用、全局监听器及记忆化缓存,避免共享导致脏数据与内存泄漏。

原型对象本身没有“缓存”可清空,真正需要清理的是挂在 prototype 上的共享数据、闭包引用或临时缓存——这些才是脏数据和内存滞留的源头。
别在 prototype 上挂可变对象
原型是所有实例共享的,一旦在 prototype 上直接赋值数组、对象或 Map,所有实例都会共用同一份数据,修改一个就影响全部,还容易让本该释放的数据长期驻留。
- ❌ 错误示例:
MyClass.prototype.items = [];—— 多个实例 push 后互相污染,且数组无法被 GC - ✅ 正确做法:把状态移到实例内部,如构造函数中初始化
this.items = []; - 或者用 WeakMap 隔离实例状态:
const state = new WeakMap(); state.set(this, { items: [] });
清理原型方法里的闭包引用
如果原型方法通过闭包捕获了 DOM 节点、大型配置或全局缓存,这些对象会被所有实例间接持有,导致无法回收。
- ⚠️ 危险写法:
MyClass.prototype.render = function() { return template + bigData.length; };(bigData在外层作用域) - ✅ 改为显式传参:
render(data),不形成闭包绑定 - 或改用静态工具函数,彻底脱离实例与原型依赖
主动管理原型上的缓存与监听器
有些场景会在 prototype 上加格式化缓存、事件监听或定时器 ID,这类资源必须配套清理逻辑,否则会持续占用内存并产生脏数据。
- 缓存类:用 WeakMap 关联实例与缓存值,实例销毁后缓存自动失效
- 监听器类:若原型方法绑定了
window.resize等全局事件,必须提供unbind()方法,并由使用者调用 - 切勿把
setTimeoutID 或AbortController挂到 prototype 上
慎用记忆化函数挂载在原型上
如果把 memoize 后的函数直接赋给 prototype,缓存对象(如 cache = {})就成了共享状态,不同实例调用会混用结果,造成脏数据。
- ❌ 错误:
MyClass.prototype.expensiveCalc = memoize(fn); - ✅ 正确:每个实例自己创建 memoized 函数,或用 WeakMap 为每个实例单独维护缓存
- 若必须共享,确保
clear()方法能访问并重置该缓存,且不干扰其他实例











