30.【TypeScript 教程】Reflect Metadata

本文涉及的产品
可视分析地图(DataV-Atlas),3 个项目,100M 存储空间
简介: 30.【TypeScript 教程】Reflect Metadata

TypeScript Reflect Metadata

本节介绍的 Reflect Metadata 主要用来在声明的时候添加和读取元数据。通过这种方式给对象添加额外的信息,是不会影响对象的结构的。

1. 解释

Reflect,翻译为『反射』,Metadata,翻译为『元数据』。反射这个概念在 Java 等众多语言中已经广泛运用,Reflect Metadata 就是通过装饰器来给类添加一些自定义的信息,然后通过反射将这些信息提取出来,也可以通过反射来添加这些信息。

2. 安装使用

通过 npm 安装这个库:

npm i reflect-metadata --save

而且需要在 tsconfig.json 中配置:

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

命令行使用:

tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata

当启用后,只要 reflect-metadata 库被引入了,设计阶段添加的类型信息可以在运行时使用。

import 'reflect-metadata'
 
@Reflect.metadata('token', 'aW1vb2M=')
class Employee {
 
  @Reflect.metadata('level', 'D2')
  salary() {
    console.log('这是个秘密')
  }
 
  @Reflect.metadata('times', 'daily')
  static meeting() {}
 
}
 
const token = Reflect.getMetadata('token', Employee)
const level = Reflect.getMetadata('level', new Employee(), 'salary')
const times = Reflect.getMetadata('times', Employee, 'meeting')
 
console.log(token) // aW1vb2M=
console.log(level) // D2
console.log(times) // daily

TIPS: 注意, 实例方法与静态方法取元数据是不同的,实例方法需要在类的实例上取元数据,静态方法直接在类上取元数据。

3. API

import 'reflect-metadata'
 
// 元数据的命令式定义,定义对象或属性的元数据
Reflect.defineMetadata(metadataKey, metadataValue, target)
Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey)
 
// 检查对象或属性的原型链上是否存在元数据键
let result = Reflect.hasMetadata(metadataKey, target)
let result = Reflect.hasMetadata(metadataKey, target, propertyKey)
 
// 检查对象或属性是否存在自己的元数据键
let result = Reflect.hasMetadata(metadataKey, target)
let result = Reflect.hasMetadata(metadataKey, target, propertyKey)
 
// 获取对象或属性原型链上元数据键的元数据值
let result = Reflect.getMetadata(metadataKey, target)
let result = Reflect.getMetadata(metadataKey, target, propertyKey)
 
// 获取对象或属性的自己的元数据键的元数据值
let result = Reflect.getOwnMetadata(metadataKey, target)
let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey)
 
// 获取对象或属性原型链上的所有元数据键
let result = Reflect.getMetadataKeys(target)
let result = Reflect.getMetadataKeys(target, propertyKey)
 
// 获取对象或属性的所有自己的元数据键
let result = Reflect.getOwnMetadataKeys(target)
let result = Reflect.getOwnMetadataKeys(target, propertyKey)
 
// 从对象或属性中删除元数据
let result = Reflect.deleteMetadata(metadataKey, target)
let result = Reflect.deleteMetadata(metadataKey, target, propertyKey)
 
// 通过装饰器将元数据应用于构造函数
@Reflect.metadata(metadataKey, metadataValue)
class C {
  // 通过装饰器将元数据应用于方法(属性)
  @Reflect.metadata(metadataKey, metadataValue)
  method() {
  }
}
 

4. 结合装饰器使用

Reflect Metadata 结合上节介绍的装饰器:

import 'reflect-metadata'
 
function get(path: string): MethodDecorator {
  return (target, name) => {
    Reflect.defineMetadata('path', path, target, name)
  }
}
 
class Employee {
  @get('/init')
  async init() {}
}
 
const metadata = Reflect.getMetadata('path', new Employee(), 'init')
console.log(metadata) // '/init'

解释: 如果经常开发 Node.js 的同学对这样的写法是不是有些熟悉呢?类方法 init() 上的装饰器 get() 传入元数据 '/init',再通过反射拿到这个路由信息,将这些路由信息进行一定的封装,然后绑定在 koa-router 上,就能达到自动加载路由的功能。

5. 小结

本节介绍了 Reflect Metadata 的一些基础使用方式,一些基础库源码如 vue-class-componentAngular 均使用了 Reflect Metadata ,有兴趣的可以深入源码学习下。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3 )前置知识要求   课程大纲 第一章 了解数据仓库概念 初步了解数据仓库是干什么的 第二章 按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章 数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章 采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章 用户行为数据仓库 严格按照企业的标准开发 第六章 搭建业务数仓理论基础和对表的分类同步 第七章 业务数仓的搭建  业务行为数仓效果图  
相关文章
|
22天前
|
JavaScript 编译器
31.【TypeScript 教程】混入(Mixins)
31.【TypeScript 教程】混入(Mixins)
17 3
|
22天前
|
JavaScript
28.【TypeScript 教程】生成器(Generator)
28.【TypeScript 教程】生成器(Generator)
24 3
|
22天前
|
JavaScript 前端开发
27.【TypeScript 教程】迭代器(Iterator)
27.【TypeScript 教程】迭代器(Iterator)
20 3
|
22天前
|
JavaScript 编译器
35.【TypeScript 教程】编译选项
35.【TypeScript 教程】编译选项
13 2
|
22天前
|
JavaScript 编译器
33.【TypeScript 教程】命名空间
33.【TypeScript 教程】命名空间
18 2
|
22天前
|
JavaScript 存储
25.【TypeScript 教程】infer 关键字
25.【TypeScript 教程】infer 关键字
18 2
|
22天前
|
JavaScript
23.【TypeScript 教程】条件类型
23.【TypeScript 教程】条件类型
11 2
|
22天前
|
JavaScript 开发者
22.【TypeScript 教程】映射类型
22.【TypeScript 教程】映射类型
14 2
|
22天前
|
索引 JavaScript 前端开发
21.【TypeScript 教程】索引类型
21.【TypeScript 教程】索引类型
17 2
|
22天前
|
JavaScript
19.【TypeScript 教程】联合类型
19.【TypeScript 教程】联合类型
11 2