JS如何实现注解?装饰器的元数据怎么添加和使用

来源:AI教程网作者:小师妹头衔:草根站长
导读:本期聚焦于小伙伴创作的《JS如何实现注解?装饰器的元数据怎么添加和使用》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JS如何实现注解?装饰器的元数据怎么添加和使用》有用,将其分享出去将是对创作者最好的鼓励。

在JavaScript中并不存在原生的注解语法,通常我们所说的JS注解其实是借助装饰器(Decorator)特性来实现的,装饰器本质是一个函数,用于在类、方法、属性等定义阶段对其添加额外的行为或修改其结构,而元数据则是附加在这些目标上的描述信息,用于后续的逻辑处理。

JS如何实现注解?装饰器的元数据怎么添加和使用

JS装饰器的基础实现

装饰器目前处于Stage 3提案阶段,在较新版本的Node.js或者配置babel插件后可以使用,基础装饰器函数接收三个参数:目标对象、属性名、属性描述符,不同类型的装饰器参数略有差异。

类装饰器示例

类装饰器接收的是类的构造函数,我们可以在这里修改类的结构或者附加信息:

// 简单的类装饰器,给类添加一个静态属性
function classDecorator(target) {
  target.isDecorated = true;
  return target;
}

@classDecorator
class User {
  constructor(name) {
    this.name = name;
  }
}

console.log(User.isDecorated); // 输出 true

方法装饰器示例

方法装饰器接收目标对象、方法名、属性描述符三个参数,可以修改方法的执行逻辑:

// 方法装饰器,给方法执行前后添加日志
function logMethod(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args) {
    console.log(`调用方法 ${propertyKey},参数:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`方法 ${propertyKey} 执行完成,结果:`, result);
    return result;
  };
  return descriptor;
}

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

const utils = new MathUtils();
utils.add(1, 2);
// 输出:
// 调用方法 add,参数: [1, 2]
// 方法 add 执行完成,结果: 3

元数据与reflect_metadata库

装饰器本身只能修改目标结构,如果我们需要给目标附加自定义的描述信息(也就是元数据),就需要借助reflect_metadata这个库,它提供了元数据的存储和读取能力,基于Reflect API扩展实现。

安装与基础使用

首先安装依赖:

npm install reflect-metadata

然后在代码入口引入该库,就可以使用相关的API了:

import 'reflect-metadata';

// 定义元数据的key
const METADATA_KEY = 'custom:metadata';

// 给对象设置元数据
const obj = {};
Reflect.defineMetadata(METADATA_KEY, { desc: '这是一个测试对象' }, obj);

// 读取元数据
const metadata = Reflect.getMetadata(METADATA_KEY, obj);
console.log(metadata); // 输出 { desc: '这是一个测试对象' }

装饰器中添加和使用元数据

我们可以把装饰器和元数据结合,在装饰器执行阶段给目标附加元数据,后续在需要的地方读取这些元数据完成逻辑处理。

自定义元数据装饰器

下面实现一个可以给类添加描述信息的装饰器:

import 'reflect-metadata';

const CLASS_METADATA_KEY = 'class:description';

// 接收描述信息作为参数的装饰器
function setClassDescription(desc) {
  return function(target) {
    // 给类附加元数据,target是类的构造函数
    Reflect.defineMetadata(CLASS_METADATA_KEY, desc, target);
    return target;
  };
}

// 读取类元数据的工具函数
function getClassDescription(target) {
  return Reflect.getMetadata(CLASS_METADATA_KEY, target);
}

// 使用装饰器
@setClassDescription('用户实体类,包含用户基础信息')
class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

// 读取元数据
const desc = getClassDescription(User);
console.log(desc); // 输出 用户实体类,包含用户基础信息

方法元数据装饰器示例

给方法添加元数据,比如标记方法是否需要权限校验:

import 'reflect-metadata';

const METHOD_METADATA_KEY = 'method:auth';

// 权限装饰器,标记方法需要的权限
function requireAuth(role) {
  return function(target, propertyKey, descriptor) {
    // 给方法附加元数据,target是类的原型对象,propertyKey是方法名
    Reflect.defineMetadata(METHOD_METADATA_KEY, role, target, propertyKey);
    return descriptor;
  };
}

// 读取方法元数据的工具函数
function getMethodAuth(target, propertyKey) {
  return Reflect.getMetadata(METHOD_METADATA_KEY, target, propertyKey);
}

class AdminController {
  @requireAuth('admin')
  deleteUser() {
    console.log('删除用户');
  }

  @requireAuth('user')
  getUserInfo() {
    console.log('获取用户信息');
  }
}

// 读取方法的权限元数据
const deleteAuth = getMethodAuth(AdminController.prototype, 'deleteUser');
const getAuth = getMethodAuth(AdminController.prototype, 'getUserInfo');
console.log(deleteAuth); // 输出 admin
console.log(getAuth); // 输出 user

不同装饰器的元数据处理差异

不同类型的装饰器,元数据的附加目标有所不同,整理如下:

装饰器类型目标对象元数据附加方式
类装饰器类的构造函数Reflect.defineMetadata(key, value, target)
方法装饰器类的原型对象、方法名Reflect.defineMetadata(key, value, target, propertyKey)
属性装饰器类的原型对象、属性名Reflect.defineMetadata(key, value, target, propertyKey)
参数装饰器类的原型对象、方法名、参数索引可以结合数组存储多个参数的元数据

注意事项

  • 使用reflect_metadata前必须确保已经引入该库,否则Reflect上不会扩展相关方法。
  • 元数据的key建议使用唯一的字符串或者Symbol,避免不同模块之间的元数据冲突。
  • 装饰器仅在类定义阶段执行一次,元数据也会在定义时就被附加,运行时读取即可。
  • 如果使用TypeScript,可以开启experimentalDecoratorsemitDecoratorMetadata配置,自动生成部分类型相关的元数据。

实际应用场景

装饰器加元数据的组合在很多框架中都有应用,比如TypeORM中通过装饰器给实体类、字段附加数据库映射的元数据,路由框架中通过装饰器标记接口的URL、请求方法等信息,这些场景都依赖于装饰器收集元数据,后续在程序启动时统一处理这些元数据完成初始化逻辑。

JS装饰器注解实现元数据reflect_metadata装饰器原理修改时间:2026-06-26 21:21:20

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。