TypeScript 装饰器入门核心用法

一、什么是装饰器?

装饰器就是普通函数 ,用 @装饰器名 贴在类、方法、属性上,作用就是给被装饰的东西加额外功能,仅此而已。

二、最基础用法:类装饰器

直接贴在类上,函数唯一参数是被装饰类的构造函数,最简单的例子:给类加静态属性。

typescript 复制代码
// 定义装饰器函数:给类加版本号
function addVersion(target) {
  target.version = '1.0.0'; // 给类挂载静态属性
}

// 用@贴在类上,完成装饰
@addVersion
class MyClass {}

// 直接使用装饰器加的属性
console.log(MyClass.version); // 输出:1.0.0

核心逻辑:@addVersion 等价于 addVersion(MyClass),把类传给装饰器函数就行。

三、最常用用法:方法装饰器

贴在类的方法上,日常用得最多,函数有 3 个固定参数:不用死记含义,跟着案例用就会。

简单案例1:给方法加日志

执行方法时,自动打印"方法被调用了",不用在方法里写重复代码。

typescript 复制代码
// 方法装饰器:打印方法调用日志
function showLog(target, name, descriptor) {
  // 保存原方法
  const oldFn = descriptor.value;
  // 重写方法,加日志逻辑
  descriptor.value = function() {
    console.log(`【日志】${name}方法被调用了`);
    oldFn.apply(this); // 执行原来的方法
  };
}

class MyClass {
  // 装饰器贴在方法上
  @showLog
  sayHi() {
    console.log('hello TS');
  }
}

new MyClass().sayHi();
// 输出:【日志】sayHi方法被调用了 → hello TS

简单案例2:禁止方法被修改

让方法只读,不能被重新赋值,避免误改方法逻辑。

typescript 复制代码
// 方法装饰器:禁止方法修改
function noChange(target, name, descriptor) {
  descriptor.writable = false; // 设为不可写
}

class MyClass {
  @noChange
  fn() {
    console.log('不能改我');
  }
}

const obj = new MyClass();
obj.fn = () => {}; // 报错:无法分配到 "fn",因为它是只读属性

四、属性装饰器:给属性加默认值

贴在类的属性上,函数有 2 个参数,最简单的用法:给属性设置默认值,不用在构造函数里初始化。

typescript 复制代码
// 属性装饰器:设置默认值
function setDefault(val) {
  return function(target, name) {
    target[name] = val;
  };
}

class MyClass {
  // 贴在属性上,传默认值
  @setDefault('张三')
  name;

  @setDefault(20)
  age;
}

console.log(new MyClass().name); // 输出:张三
console.log(new MyClass().age); // 输出:20

五、装饰器工厂:给装饰器传参

想给装饰器传自定义参数(比如日志加前缀、默认值自定义),就写装饰器工厂------本质是「返回装饰器的函数」,写法超简单,看案例就会。

案例:带前缀的日志装饰器

让日志有自定义前缀,不用写多个装饰器函数。

typescript 复制代码
// 装饰器工厂:接收自定义前缀
function log(prefix) {
  // 返回真正的装饰器函数
  return function(target, name, descriptor) {
    const oldFn = descriptor.value;
    descriptor.value = function() {
      console.log(`【${prefix}】${name}方法执行了`);
      oldFn.apply(this);
    };
  };
}

class MyClass {
  // 传参使用:自定义前缀"接口请求"
  @log('接口请求')
  getData() {}

  // 传参使用:自定义前缀"操作"
  @log('操作')
  saveData() {}
}

new MyClass().getData(); // 输出:【接口请求】getData方法执行了
new MyClass().saveData(); // 输出:【操作】saveData方法执行了

六、必记规则:多个装饰器的执行顺序

一个类/方法上贴多个装饰器时,从下往上执行------谁离被装饰的东西近,谁先执行。

typescript 复制代码
// 定义两个简单装饰器
function A(target) {
  console.log('执行装饰器A');
  return target;
}
function B(target) {
  console.log('执行装饰器B');
  return target;
}

// B离类更近,先执行;A后执行
@A
@B
class MyClass {}

// 运行结果:先打印「执行装饰器B」,再打印「执行装饰器A」

等价理解:MyClass = A(B(MyClass)),先执行内层的 B,再执行外层的 A。

七、使用前提:开启TS配置

装饰器是 TS 实验性特性,必须在 tsconfig.json 里加一行配置,否则报错,就加这一个核心项就行:

json 复制代码
{
  "compilerOptions": {
    "experimentalDecorators": true, // 必须开启,启用装饰器
    "target": "ES5" // 项目基本配置,一般都有
  }
}
相关推荐
EnCi Zheng3 小时前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen3 小时前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技3 小时前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人3 小时前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实3 小时前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha4 小时前
三目运算符
linux·服务器·前端
晓晨的博客4 小时前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect4 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
donecoding4 小时前
别再让 pnpm 跟着 nvm 跑了!独立安装终极指南
前端·node.js·前端工程化
不可能的是4 小时前
从 /simplify 指令深挖 Claude Code 多 Agent 协同机制
javascript