当前位置:首页 > JavaScript

js怎么实现装饰器

2026-01-31 00:47:27JavaScript

装饰器基础概念

装饰器是一种特殊函数,用于修改类、方法或属性的行为。在JavaScript中,装饰器通过@符号调用,目前处于提案阶段(Stage 3),需通过Babel或TypeScript编译支持。

环境配置

使用装饰器需配置Babel或TypeScript:

  • Babel:安装@babel/plugin-proposal-decorators插件,配置.babelrc
    {
      "plugins": [
        ["@babel/plugin-proposal-decorators", { "legacy": true }]
      ]
    }
  • TypeScript:在tsconfig.json中启用:
    {
      "compilerOptions": {
        "experimentalDecorators": true
      }
    }

类装饰器

类装饰器接收目标类构造函数,可扩展或修改类:

js怎么实现装饰器

function logClass(target) {
  console.log(`Class ${target.name} decorated`);
  // 添加原型方法
  target.prototype.print = () => console.log('Decorated method');
}

@logClass
class MyClass {}
const instance = new MyClass();
instance.print(); // 输出: "Decorated method"

方法装饰器

方法装饰器接收三个参数:目标对象、方法名、属性描述符。常用于拦截方法调用:

function readonly(target, name, descriptor) {
  descriptor.writable = false;
  return descriptor;
}

class User {
  @readonly
  getName() { return 'John'; }
}

const user = new User();
user.getName = () => 'Hack'; // 报错:无法重写只读方法

属性装饰器

属性装饰器接收目标对象和属性名,常用于元数据标记:

js怎么实现装饰器

function format(formatString) {
  return function (target, key) {
    Reflect.defineMetadata('format', formatString, target, key);
  };
}

class Book {
  @format('YYYY-MM-DD')
  publishDate = '2023-01-01';
}

// 通过反射获取元数据
const metadata = Reflect.getMetadata('format', Book.prototype, 'publishDate');
console.log(metadata); // 输出: "YYYY-MM-DD"

参数装饰器

参数装饰器用于标记方法参数,接收目标对象、方法名和参数索引:

function validate(type) {
  return function (target, key, index) {
    Reflect.defineMetadata('validate', { type, index }, target, key);
  };
}

class ApiService {
  fetch(@validate('number') id) {
    return { data: id };
  }
}

装饰器工厂

通过高阶函数实现可配置装饰器:

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

class Logger {
  @delay(1000)
  log(message) {
    console.log(message);
  }
}

const logger = new Logger();
logger.log('Delayed message'); // 1秒后输出

注意事项

  • 装饰器在类定义时执行,而非实例化时。
  • 装饰器不能用于函数(因存在函数提升)。
  • 第三方库如core-decorators提供常用装饰器(如@deprecated)。

通过组合不同类型的装饰器,可实现AOP(面向切面编程)、日志、权限控制等复杂功能。

标签: js
分享给朋友:

相关文章

js实现验证码

js实现验证码

实现验证码的JavaScript方法 生成随机验证码 使用Math.random()生成随机字符串,结合数字和字母: function generateCaptcha() { const cha…

js实现动画

js实现动画

使用 CSS 动画与 JavaScript 控制 通过 JavaScript 动态添加或移除 CSS 类来触发动画。CSS 定义关键帧(@keyframes),JavaScript 通过 classL…

js实现抽奖

js实现抽奖

实现抽奖功能的基本思路 抽奖功能的核心是随机选择奖项并展示结果。可以通过数组存储奖项,利用随机数生成索引,最后通过动画增强用户体验。 准备奖项数据 定义一个数组存储奖项信息,每个奖项可以包含名称、图…

js实现图片

js实现图片

图片加载与显示 在JavaScript中,可以通过Image对象动态加载图片。创建实例后设置src属性触发加载,通过onload回调处理加载完成后的操作: const img = new Ima…

js 实现递归

js 实现递归

递归的基本概念 递归是指函数直接或间接调用自身的过程。在JavaScript中,递归通常用于解决可以分解为相似子问题的问题,如阶乘、斐波那契数列、树形结构遍历等。 递归的实现要点 基线条件(Base…

js实现排序

js实现排序

数组排序方法 JavaScript提供了内置的sort()方法用于数组排序。默认情况下,sort()将元素转换为字符串并按照Unicode码点排序。对于数字排序,需传入比较函数。 const num…