应从设计源头减少对原型链的依赖,核心是让属性方法就近存在;优先用组合代替继承,高频访问属性尽量实例化,纯字典场景用object.create(null),谨慎扩展内置原型。

从设计源头减少对原型链的依赖,核心是让属性和方法尽可能“就近”存在——不靠查找,而靠直接持有。这不是放弃原型复用,而是有意识地划分职责:哪些该共享(放原型),哪些该私有(放实例),哪些根本不需要继承(用纯数据结构)。
优先用组合代替继承
当多个对象需要相似能力时,与其构造深层继承链,不如把能力拆成独立模块,在实例中显式组合。
- 比如“可拖拽”“可缩放”“可序列化”这些行为,封装成工具对象或类,通过实例属性引入:
obj.dragger = new Dragger(obj) - 避免写
class Chart extends Plot extends View extends Component这种长链;改用chart.behaviors = { plot: new Plot(), zoom: new Zoomer() } - 组合后,关键操作都在实例上,访问路径稳定,引擎也更容易优化
高频访问属性尽量实现实例化
如果某个属性被反复读取(如item.id、node.type),哪怕它逻辑上属于“类型共性”,也值得在构造时复制到实例。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 构造函数中直接赋值:
this.type = 'button';,而不是依赖Button.prototype.type - 对计算开销大的属性,首次访问后缓存:
Object.defineProperty(this, 'computedData', { value: expensiveCalc(), writable: false }) - 注意平衡:不是所有属性都需实例化,仅针对读多写少、调用频次高的字段
用Object.create(null)隔离纯字典场景
当你只做键值存储、不需继承任何默认方法(如toString、hasOwnProperty),就该主动切断原型链。
- 比如配置映射表、事件监听器注册表、缓存Map:
const cache = Object.create(null); cache['key'] = value; - 这样既避免了原型上意外属性干扰(如
cache.toString被覆盖导致遍历出错),又消除了所有原型查找开销 - 配合
Object.hasOwn(cache, key)(推荐)或hasOwnProperty.call(cache, key)做安全判断
谨慎扩展内置原型,明确边界
全局修改Array.prototype或Object.prototype看似方便,实则污染环境、破坏封装、增加不可控的原型链长度。
- 如需通用工具方法,优先定义独立函数:
arrayUtils.flatten(arr),而非arr.flatten() - 若必须扩展,限定作用域(如仅在模块内
Object.assign(Array.prototype, { myMethod() {} })),并确保不覆盖原生方法 - 第三方库若擅自扩展会带来隐式依赖,可在项目入口用
Object.freeze(Object.prototype)(开发期)提前暴露问题
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










