当前位置:首页 > 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中实现全选功能通常涉及监听全选复选框的点击事件,并根据其状态控制其他复选框的选中状态。以下是几种常见的实现方式: 基础DOM操作实现 通过获取所有目标复选框…

js jquery

js jquery

jQuery 简介 jQuery 是一个快速、简洁的 JavaScript 库,简化了 HTML 文档遍历、事件处理、动画设计和 Ajax 交互。它兼容多种浏览器,提供易于使用的 API,使开发者能够…

js实现变形

js实现变形

使用 CSS 和 JavaScript 实现元素变形 在 JavaScript 中实现变形效果通常结合 CSS 的 transform 属性,通过动态修改该属性实现元素的旋转、缩放、倾斜或平移。 基…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: functio…

js实现 功能

js实现 功能

在 JavaScript 中实现功能通常涉及多个关键步骤,具体取决于功能需求。以下是常见功能的实现方法和示例: 基本功能实现 使用函数封装逻辑是最直接的方式。例如,实现一个计算两数之和的函数: f…

js实现轮播代码

js实现轮播代码

基础轮播实现 使用HTML、CSS和JavaScript创建一个简单的轮播效果。HTML部分定义轮播容器和图片元素。 <div class="carousel"> <div c…