核心思路是将高频访问属性提前挂载到实例上以避免原型链查找。具体包括:构造函数中直接赋值只读字段;绑定或缓存高频调用方法;静态工具定义为static;WeakMap缓存动态计算结果;控制原型链深度≤2层;纯数据容器用Object.create(null);改继承为组合。

核心思路是:不靠“拷贝”解决访问问题,而是让属性访问本身不依赖深链查找——把高频访问的属性提前落到实例上,同时避免原型链过长和运行时修改。
把常用属性直接挂到实例上
构造函数里就赋值,而不是等每次访问时再沿原型链一层层找。比如主题配置、API 地址、默认状态这些只读或低频变更的字段:
- 写成 this.baseUrl = options.baseUrl || '/api',而不是每次调用
getApiBase() - 解构传入参数后直接挂载:
const { timeout, retry } = options; this.timeout = timeout; this.retry = retry; - 注意前提:这些值不依赖父级动态响应(如 Vue 的响应式 props),否则会断开联动
缓存原型方法引用
事件处理器、渲染函数这类在循环或帧内高频调用的方法,每次执行都要查原型链。提前绑定或赋值能跳过查找:
- this.handleClick = this.handleClick.bind(this) —— 绑定后调用直接执行,不走链
- 或直接缓存:this._render = super.render,适用于父类方法稳定、无需动态切换的场景
- 静态工具方法(如日期格式化)优先定义为
static,完全绕过实例和原型链
用 WeakMap 缓存动态计算结果
有些属性无法提前挂实(比如根据用户权限实时计算的菜单项),又不能每次都深查。WeakMap 是理想选择:
- 定义全局缓存:
const menuCache = new WeakMap() - 首次访问时计算并存入:
if (!menuCache.has(this)) menuCache.set(this, computeMenu(this)) - 后续直接
menuCache.get(this),无原型遍历,对象销毁后自动清理 - 适合组件实例、表单字段等生命周期明确的对象
从设计源头控制链深与依赖
深拷贝开销往往源于原型链太深、属性太“飘”,而非拷贝本身。优化要前置:
- V8 对超过 4 层的原型链会逐步放弃内联缓存,性能明显下降;业务类建议 ≤2 层:实例 → 业务原型 → null
- 纯数据容器(如路由参数、临时映射)用
Object.create(null)创建,彻底切断默认链 - 避免为复用一两个方法新建继承层级;改用组合:
this.formatter = new DateFormatter()或私有字段 + 方法代理 - 多层 UI 组件链(如 Button ← IconButton ← BaseButton)可抽离 emitter、validator 等能力为独立持有对象
不复杂但容易忽略:真正拖慢速度的往往不是嵌套本身,而是属性不在实例上、又不得不每次都向上翻好几层找。

















