当前位置:首页 > JavaScript

js实现decorator

2026-02-01 03:15:36JavaScript

JavaScript 装饰器实现

装饰器是一种特殊类型的声明,可以附加到类、方法、访问器、属性或参数上。装饰器使用 @expression 形式,expression 必须求值为一个函数,该函数会在运行时被调用。

类装饰器

类装饰器应用于类的构造函数,可以用来观察、修改或替换类定义。

function logClass(target) {
  console.log('Class decorator applied to:', target.name);
  return target;
}

@logClass
class MyClass {
  constructor() {
    console.log('MyClass instance created');
  }
}

const instance = new MyClass();

方法装饰器

方法装饰器应用于方法的属性描述符,可以用来修改方法的行为。

function logMethod(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function(...args) {
    console.log(`Calling method ${propertyKey} with args:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`Method ${propertyKey} returned:`, result);
    return result;
  };

  return descriptor;
}

class Calculator {
  @logMethod
  add(a, b) {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3);

属性装饰器

属性装饰器应用于类的属性,可以用来修改属性的行为。

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

class Person {
  @readonly
  name = 'John';
}

const person = new Person();
person.name = 'Jane'; // 会报错,因为属性是只读的

访问器装饰器

访问器装饰器应用于访问器的属性描述符,可以用来修改 getter 或 setter 的行为。

js实现decorator

function configurable(value) {
  return function(target, propertyKey, descriptor) {
    descriptor.configurable = value;
    return descriptor;
  };
}

class Circle {
  private _radius: number;

  constructor(radius: number) {
    this._radius = radius;
  }

  @configurable(false)
  get radius() {
    return this._radius;
  }
}

参数装饰器

参数装饰器应用于构造函数或方法的参数,可以用来添加元数据。

function validate(target, propertyKey, parameterIndex) {
  console.log(`Validating parameter ${parameterIndex} of ${propertyKey}`);
}

class Greeter {
  greet(@validate name: string) {
    console.log(`Hello, ${name}`);
  }
}

const greeter = new Greeter();
greeter.greet('World');

装饰器工厂

装饰器工厂是一个返回装饰器函数的函数,可以用来配置装饰器的行为。

function log(message: string) {
  return function(target, propertyKey, descriptor) {
    console.log(message);
    return descriptor;
  };
}

class Logger {
  @log('Logging method called')
  logMessage(message: string) {
    console.log(message);
  }
}

const logger = new Logger();
logger.logMessage('Hello, world!');

TypeScript 中的装饰器

在 TypeScript 中,需要启用 experimentalDecorators 编译器选项才能使用装饰器。

js实现decorator

{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

Babel 中的装饰器

使用 Babel 时,需要安装 @babel/plugin-proposal-decorators 插件来支持装饰器语法。

npm install --save-dev @babel/plugin-proposal-decorators

然后在 .babelrc 中配置插件:

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
  ]
}

注意事项

装饰器目前是 ECMAScript 的提案,尚未成为正式标准。在使用时需要注意兼容性问题。

装饰器的执行顺序是从上到下,从外到内。对于同一个目标,多个装饰器的应用顺序如下:

  1. 参数装饰器
  2. 方法/访问器/属性装饰器
  3. 类装饰器

标签: jsdecorator
分享给朋友:

相关文章

js实现

js实现

实现 JavaScript 功能的方法 在 JavaScript 中实现特定功能通常涉及多个步骤。以下是常见的实现方法: 基础语法和变量声明 使用 let 或 const 声明变量: let co…

js实现分页

js实现分页

分页的基本实现思路 在JavaScript中实现分页功能通常需要结合前端和后端逻辑。前端负责渲染分页控件和处理用户交互,后端负责提供分页数据。 前端分页实现 纯前端分页适用于数据量较小的情况,可以…

js实现文件下载

js实现文件下载

使用 a 标签下载文件 通过动态创建 a 标签并设置 download 属性实现文件下载。适用于已知文件 URL 或 Blob 数据的情况。 function downloadFile(url, f…

js实现全选

js实现全选

实现全选功能的方法 在JavaScript中实现全选功能通常涉及监听全选复选框的点击事件,并根据其状态控制其他复选框的选中状态。以下是几种常见的实现方式: 基础DOM操作实现 通过获取所有目标复选…

js实现复制到剪贴板

js实现复制到剪贴板

使用document.execCommand方法(传统方式,已废弃但部分浏览器仍支持) 该方法适用于旧版浏览器,但已被标记为废弃。执行前需确保文本已被选中: function copyToClipb…

js轮播图实现原理

js轮播图实现原理

轮播图的基本原理 轮播图通过动态切换显示的内容(图片、文本等)实现视觉上的滑动效果。核心原理是利用CSS和JavaScript控制元素的显示与隐藏,或通过变换位置实现滑动动画。 实现方法一:…