javascript装饰器模式通过原型链动态增强对象行为,核心是不修改原构造函数而注入新功能:创建返回增强构造函数的装饰器,继承原原型并挂载方法;支持链式叠加与方法级包装;现代更推荐proxy或函数组合。

JavaScript 中的装饰器模式不依赖语言原生语法(如 TypeScript 的 @ 装饰器),而是通过原型链动态增强对象行为——核心在于让被装饰对象保留原有原型,同时将新功能“注入”到其原型或实例上。
用原型链实现轻量级装饰
装饰器本质是“在不修改原构造函数的前提下,为其添加能力”。可行做法是创建一个装饰函数,接收原构造函数,返回增强后的新构造函数,并确保其实例仍能访问原构造函数的原型方法:
- 新建装饰器函数,参数为原始构造函数
Target - 定义新构造函数
Decorator,内部调用Target.call(this, ...args)保证初始化逻辑执行 - 设置
Decorator.prototype = Object.create(Target.prototype),继承原有方法 - 在
Decorator.prototype上挂载新增方法(如logAction、validate) - 返回
Decorator,它既是新类,又与原类保持原型连通
避免原型污染,用 Object.assign 安全扩展
直接修改 Target.prototype 属于侵入式增强,违背装饰器“可选叠加”原则。更稳妥的方式是:只在装饰器自己的原型上添加方法,并通过 Object.assign 把装饰方法复制到实例,或使用 Object.setPrototypeOf 临时桥接:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 创建装饰实例时,用
Object.setPrototypeOf(instance, Decorator.prototype)动态挂载增强原型 - 若需多个装饰层,可链式调用:
withLogging(withValidation(User)),每次返回新构造函数,原型链逐层延伸 - 注意:不能用
class extends硬继承,否则会切断与原始原型的直接关联,失去“装饰”语义
结合 call/apply 实现方法级装饰
对单个方法做装饰(如加日志、节流),可用高阶函数包裹原方法,并绑定到实例上下文:
- 在装饰器中获取目标方法:
const original = target[key] - 用
function(...args) { console.log('before'); const ret = original.apply(this, args); console.log('after'); return ret; } - 将包装后的方法赋回实例或原型,确保
this指向正确(用bind或箭头函数维持上下文) - 典型场景:给
User.prototype.save添加自动序列化前校验
兼容性与现代替代建议
ES6+ 中,更推荐用组合函数或代理(Proxy)替代原型装饰,尤其当需拦截读写、方法调用等动态行为时:
-
Proxy可无侵入地拦截任意操作,比原型补丁更灵活、更安全 - 纯函数组合(如
compose(log, validate, save))更适合函数式风格,不依赖this和原型 - 若必须用原型,应优先使用
Object.defineProperty控制属性可枚举性与可写性,防止装饰方法暴露在for...in中
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










