关键在于数据与行为分离:实例字段存专属数据,方法统一挂原型上;10,000实例可省约15MB内存;公共字段仅放需独享的数据如userId、isOnline、cache;方法须定义在原型链,避免类字段语法声明函数;字段不可通过原型访问,验证需查实例本身;高频对象可用工厂+reset()池化复用。

关键在于把数据和行为分开存放:实例字段存专属数据,方法统一挂原型上。这样 10,000 个实例不会重复创建函数,能省下约 15MB 内存(Chrome DevTools 实测数据)。
公共实例字段只放真正需要每个实例独有一份的数据
比如用户 ID、临时状态、配置快照等——这些值在构造时确定,且不同实例间互不影响。它们不是定义在 prototype 上的,而是在 constructor 执行时直接赋给 this 的独立属性。
- ✅ 正确用法:
userId = 'U123';、isOnline = true;、cache = new Map(); - ❌ 避免写法:
render = () => { ... };或handleClick = function() { ... };—— 这会让每个实例都生成新函数,破坏内存优化
所有可复用的方法必须定义在原型链上
类中声明的普通方法(如 save()、validate())默认就落在 ClassName.prototype 上,这是安全的。你也可以显式检查:MyClass.prototype.save 存在且是函数。
- 确保不把方法写成类字段形式(如
save = () => { ... }),那会绑定到实例,失去共享性 - 若需访问实例字段,优先用普通方法语法;箭头函数仅用于需要自动绑定
this的回调场景(如事件监听器),且应谨慎评估是否真需每个实例一份
避免意外污染原型或覆盖实例字段
公共实例字段无法通过原型访问,MyClass.prototype.myField 永远是 undefined。这点常被误判为“没定义成功”,其实是设计使然。
- 想验证字段是否生效?查实例本身:
instance.myField !== undefined - 不要试图在原型上设置同名属性来“兜底”,它不会参与实例字段查找(字段查找只走
this,不走原型链) - 若需默认值逻辑复杂,可在 constructor 中初始化,而非依赖字段语法(字段语法适合简单字面量初始化)
配合工厂或池化进一步降低 GC 压力
对高频创建/销毁的业务对象(如游戏实体、实时消息处理器),可封装一个轻量工厂:
- 复用已创建的实例(重置字段值 + 调用 reset() 方法),避免频繁 new/delete
- reset() 是一个原型方法,负责清空或重置所有实例字段,保持原型方法不变
- 字段仍用公共语法声明,保证结构清晰;reset() 内部只操作
this.xxx = newValue,不新增函数

















