当前位置:首页 > JavaScript

js 实现装饰器

2026-04-07 10:53:21JavaScript

装饰器基础概念

装饰器是一种特殊类型的声明,能够附加到类声明、方法、属性或参数上,以修改或扩展其行为。在 JavaScript 中,装饰器通过 @ 符号前缀使用,本质上是高阶函数。

环境配置

装饰器目前处于提案阶段(Stage 3),需通过 Babel 或 TypeScript 编译支持:

  1. Babel 配置:安装 @babel/plugin-proposal-decorators 插件并启用 legacy: true
  2. TypeScript:在 tsconfig.json 中设置 "experimentalDecorators": true

类装饰器

类装饰器接收目标类的构造函数作为参数,可用于修改或替换类定义:

function logClass(target) {
  console.log(`Class ${target.name} decorated`);
  return class extends target {
    constructor(...args) {
      super(...args);
      console.log('Instance created');
    }
  };
}

@logClass
class MyClass {}
new MyClass(); // 输出: "Class MyClass decorated" 和 "Instance created"

方法装饰器

方法装饰器接收三个参数:目标类原型、方法名、属性描述符。常用于拦截或增强方法逻辑:

function logMethod(target, name, descriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args) {
    console.log(`Calling ${name} with args:`, args);
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class Calculator {
  @logMethod
  add(a, b) {
    return a + b;
  }
}
new Calculator().add(2, 3); // 输出: "Calling add with args: [2, 3]"

属性装饰器

属性装饰器接收目标类原型和属性名,常用于标记或修改属性:

function readonly(target, key) {
  Object.defineProperty(target, key, { writable: false });
}

class User {
  @readonly
  name = 'Alice';
}
const user = new User();
user.name = 'Bob'; // 报错: Cannot assign to read only property

参数装饰器

参数装饰器接收目标类原型、方法名和参数索引,通常用于依赖注入或参数验证:

function validateParam(target, methodName, paramIndex) {
  console.log(`Validating parameter ${paramIndex} of ${methodName}`);
}

class ApiService {
  fetchData(@validateParam id) {
    return { data: `ID: ${id}` };
  }
}
new ApiService().fetchData(123); // 输出: "Validating parameter 0 of fetchData"

装饰器工厂

通过高阶函数生成可配置的装饰器:

js 实现装饰器

function delay(ms) {
  return function(target, name, descriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function(...args) {
      setTimeout(() => originalMethod.apply(this, args), ms);
    };
    return descriptor;
  };
}

class Task {
  @delay(1000)
  run() {
    console.log('Task executed after 1s');
  }
}
new Task().run(); // 1秒后输出

注意事项

  1. 装饰器执行顺序:属性/方法/参数装饰器从右到左,类装饰器最后执行。
  2. 避免在装饰器中直接修改原型链,可能导致不可预期行为。
  3. 生产环境需确保编译工具链支持装饰器语法。

标签: js
分享给朋友:

相关文章

js实现倒计时

js实现倒计时

实现倒计时的基本方法 使用 JavaScript 实现倒计时功能可以通过 setInterval 或 setTimeout 结合日期计算来完成。以下是几种常见的实现方式: 使用 setInterva…

jquery.js

jquery.js

jQuery 简介 jQuery 是一个快速、简洁的 JavaScript 库,用于简化 HTML 文档遍历、事件处理、动画设计和 Ajax 交互。它的设计宗旨是“Write Less, Do Mor…

css3结合js制作

css3结合js制作

CSS3 结合 JavaScript 制作动态效果 CSS3 和 JavaScript 结合可以实现丰富的动态效果,包括动画、交互和响应式设计。以下是几种常见的实现方式: CSS3 动画与 Java…

js实现图片上传

js实现图片上传

图片上传的基本实现 使用HTML的<input type="file">元素配合JavaScript的File API可以实现图片上传功能。HTML部分需要创建一个文件选择输入框和一个用于…

js实现二叉树

js实现二叉树

二叉树的基本概念 二叉树是一种树形数据结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的常见操作包括插入、删除、遍历等。 二叉树的节点定义 在JavaScript中,二叉树的节点可…

js实现求导

js实现求导

实现数值求导的方法 在JavaScript中实现求导通常采用数值方法,因为JavaScript不是符号计算语言。以下是常见的数值微分方法: 中心差分法 中心差分法提供较高精度的导数近似:…