什么是javascript的装饰器_如何用它增强类或方法?

8次阅读

JavaScript 装饰器是 Stage 3 提案,需 Babel 或 TS 编译支持;本质是接收目标、名称、描述符并返回新描述符的运行时高阶函数;类装饰器改构造函数,方法装饰器须显式返回修改后的 descriptor。

什么是 javascript 的装饰器_如何用它增强类或方法?

JavaScript 的装饰器目前仍是 Stage 3 提案,未被正式纳入语言标准,class 和方法上的 @decorator 语法在原生环境中默认不可用——必须依赖 Babel(@babel/plugin-proposal-decorators)或 TypeScript 编译支持。

装饰器本质是函数,接收目标、名称、描述符并返回新描述符

装饰器不是语法糖,而是运行时可执行的高阶函数。类装饰器接收 target(构造函数),方法装饰器接收 target(原型)、name(方法名)、descriptor(属性描述符)。你修改 descriptor.value 就等于替换了原始方法。

常见错误:直接在装饰器里写 return function() {……} 却忘了重新赋值给 descriptor.value,导致装饰无效。

  • 方法装饰器必须显式返回修改后的 descriptor,否则行为不变
  • 类装饰器可返回新构造函数,但需谨慎处理 instanceof 和原型链
  • Babel 默认使用 legacy: true 模式,此时 descriptor 是“旧式”对象(无 initializer),TypeScript 则按提案最新语义处理

用 @log 装饰方法:捕获调用、参数与返回值

这是最典型的入门场景。注意不能只靠 console.log,要保留原方法的 this 绑定和返回值,否则会破坏调用链。

立即学习Java 免费学习笔记(深入)”;

function log(target, name, descriptor) {const original = descriptor.value;   descriptor.value = function(……args) {console.log(`[LOG] ${name} called with`, args);     const result = original.apply(this, args);     console.log(`[LOG] ${name} returned`, result);     return result;   };   return descriptor; }  class Calculator {@log   add(a, b) {return a + b;} }

关键点:

  • original.apply(this, args) 保证 this 正确指向实例
  • 必须返回 result,否则所有被装饰方法都返回 undefined
  • 若方法是异步的,需单独处理 asyncPromise 返回值

@readonly 和 @configurable:操作属性描述符的底层控制

这些装饰器直接改写 descriptor 的布尔标志,属于元编程中最基础也最容易出错的操作。

典型陷阱:Object.defineProperty 在严格模式下对不可配置属性重复设置会抛 TypeError;装饰器链中多个装饰器同时修改同一描述符,顺序会影响最终结果。

  • @readonly 应设 descriptor.writable = false,且通常配合 configurable: false 防止后续覆盖
  • @nonenumerabledescriptor.enumerable = false,避免该方法出现在 for……inObject.keys()
  • 不要在装饰器里调用 Object.defineProperty(target, name, descriptor) —— 这是 Babel/TS 编译器的工作,手动调用会导致重复定义报错

TypeScript 中装饰器与类型检查的脱节问题

TypeScript 编译器仅校验装饰器调用语法,不校验装饰器内部逻辑是否真能改变类型行为。比如你写了 @deprecated,TS 不会阻止你继续调用该方法,也不会自动推导返回值类型变化。

更隐蔽的问题:装饰器返回新函数后,原方法的 JSDoc 注释、参数类型、this 类型注解不会自动继承。你需要手动在装饰器内部用 as any 或泛型透传类型,或借助 ReturnType / Parameters 工具 类型增强返回签名。

真正难的从来不是写一个装饰器,而是让装饰后的类仍能通过严格类型检查、被 IDE 正确跳转、在 bundle 分析中保持可读性——这些细节在快速原型阶段常被忽略,上线后才暴露。

text=ZqhQzanResources