js元数据入门

一、JavaScript 原生元数据

1. 函数/对象的固有元数据
function example(a, b) {}
console.log(example.name);    // "example"(函数名)
console.log(example.length);  // 2(参数个数)
2. Symbol 类型元数据

ES6 的 Symbol 可作为唯一元数据标识:

const META = Symbol('metadata');
const obj = {
  [META]: { version: 1.0, author: 'Alice' }
};
console.log(obj[META]); // { version: 1.0, author: 'Alice' }

二、TypeScript 元数据(需配合装饰器)

1. 编译配置

需启用 tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}
2. 反射元数据 API

使用 reflect-metadata 库:

import 'reflect-metadata';

class User {
  @Reflect.metadata('role', 'admin')
  login() {}
}

const meta = Reflect.getMetadata('role', User.prototype, 'login');
console.log(meta); // 'admin'

三、装饰器中的元数据

1. 类装饰器元数据
function Injectable() {
  return (target: Function) => {
    Reflect.defineMetadata('service', true, target);
  };
}

@Injectable()
class DataService {}

const isService = Reflect.getMetadata('service', DataService);
console.log(isService); // true
2. 参数装饰器元数据
function ParamType(type: any) {
  return (target: Object, key: string, index: number) => {
    Reflect.defineMetadata(`param_${key}_${index}`, type, target);
  };
}

class Controller {
  getUser(@ParamType(String) id: string) {}
}

const paramType = Reflect.getMetadata('param_getUser_0', Controller.prototype);
console.log(paramType); // String

四、元数据应用场景

1. 依赖注入框架
// 伪代码示例
class Container {
  resolve(target: Function) {
    const dependencies = Reflect.getMetadata('design:paramtypes', target);
    // 根据参数类型实例化依赖
  }
}
2. API 文档生成

通过解析元数据自动生成 Swagger 文档:

@ApiController('/users')
class UserController {
  @Get('/:id')
  @ApiResponse({ status: 200, type: User })
  getUser(@Path() id: string) {}
}
3. 序列化/反序列化
class Serializer {
  serialize(obj: Object) {
    const metadata = Reflect.getMetadata('serialization', obj.constructor);
    // 根据元数据规则转换对象
  }
}

五、高级技巧

1. 元数据继承
function InheritMetadata() {
  return (target: Function) => {
    const parentMeta = Reflect.getMetadata('custom', Object.getPrototypeOf(target));
    Reflect.defineMetadata('custom', parentMeta, target);
  };
}
2. 元数据验证
function Validate() {
  return (target: Object, key: string) => {
    const type = Reflect.getMetadata('design:type', target, key);
    // 根据类型进行运行时验证
  };
}

六、注意事项

  1. 性能影响:元数据操作会带来运行时开销
  2. 类型擦除:TypeScript 元数据在编译后可能丢失类型细节
  3. 兼容性:需配合 Babel 插件或 TypeScript 编译

七、推荐工具库

  1. reflect-metadata:官方元数据反射库
  2. class-validator:基于装饰器的验证库
  3. typedi:轻量级依赖注入容器
  4. routing-controllers:基于装饰器的路由框架

通过合理使用元数据,可以实现声明式编程、减少样板代码,并提升代码的可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值