WHAT - reflect-metadata

目录

  • 一、介绍
    • 1.1 产生背景
    • 1.2 目标
    • 1.2 主要功能
  • 二、对象的元数据
  • 三、场景:依赖注入
  • 四、场景:ORM(对象关系映射)

一、介绍

reflect-metadata 是一个JavaScript库,用于在运行时获取和操作JavaScript对象的元数据。它提供了一组装饰器(decorators)和一些辅助函数,用于在JavaScript类和成员上添加、读取和修改元数据。

1.1 产生背景

  • Decorators add the ability to augment a class and its members as the class is defined, through a declarative syntax. 装饰器通过声明式语法,在定义类时为类及其成员提供了扩展的能力。
  • Traceur attaches annotations to a static property on the class. Traceur 将注解附加到类的静态属性上。
  • Languages like C# (.NET), and Java support attributes or annotations that add metadata to types, along with a reflective API for reading metadata. C# (.NET)Java 等编程语言支持属性或注解,可以向类型添加元数据,并提供反射API来读取元数据。

1.2 目标

  • A number of use cases (Composition/Dependency Injection, Runtime Type Assertions, Reflection/Mirroring, Testing) want the ability to add additional metadata to a class in a consistent manner. 许多用例(组合/依赖注入、运行时类型断言、反射/镜像、测试)希望能够以一致的方式向类添加额外的元数据。
  • A consistent approach is needed for various tools and libraries to be able to reason over metadata. 需要一种一致的方法,使得各种工具和库能够对元数据进行推理。
  • Metadata-producing decorators (nee. “Annotations”) need to be generally composable with mutating decorators. 生成元数据的装饰器(原名“注解”)需要能够与修改装饰器进行一般化的组合。
  • Metadata should be available not only on an object but also through a Proxy, with related traps. 元数据不仅应该在对象上可用,还应该通过代理对象以及相关的 traps 进行访问。
  • Defining new metadata-producing decorators should not be arduous or over-complex for a developer. 对于开发人员来说,定义新的生成元数据的装饰器不应该是繁琐或过于复杂的。
  • Metadata should be consistent with other language and runtime features of ECMAScript. 元数据应该与ECMAScript的其他语言和运行时特性保持一致。

1.2 主要功能

  1. 添加元数据:使用装饰器将元数据添加到类、方法、属性等上。例如,可以使用@Reflect.metadata()装饰器将元数据附加到一个类或方法上。
class C {@Reflect.metadata(metadataKey, metadataValue)method() {}
}// equals to
// 自定义一个装饰器来添加元数据
function MyMetadata(key: string, value: any) {return function(target: any, propertyKey: string) {Reflect.defineMetadata(key, value, target, propertyKey);};
}
  1. 读取元数据:使用Reflect.getMetadata()函数读取已添加的元数据。可以通过提供元数据的键来获取相应的元数据值。
let obj = new C();
let metadataValue = Reflect.getMetadata(metadataKey, obj, "method");
  1. 修改元数据:使用Reflect.defineMetadata()函数修改已添加的元数据。可以通过提供元数据的键和新的元数据值来修改元数据。
Reflect.defineMetadata(metadataKey, metadataValue, C.prototype, "method");

完整实例:

import 'reflect-metadata';// 定义一个类,并在其中的方法上添加元数据
class MyClass {@Reflect.metadata('type', 'user')@Reflect.metadata('name', 'John')myMethod() {}
}// 读取元数据
const type = Reflect.getMetadata('type', MyClass.prototype, 'myMethod');
const name = Reflect.getMetadata('name', MyClass.prototype, 'myMethod');console.log(type); // 'user'
console.log(name); // 'John'

通过使用reflect-metadata,可以在运行时动态地为对象添加附加信息,这对于一些需要在运行时进行元数据操作的场景非常有用,例如在依赖注入、==ORM(对象关系映射)==等方面。

需要注意的是,reflect-metadata是一个第三方库,需要在项目中引入并使用。它在TypeScript中广泛使用,但也可以用于纯JavaScript项目中。

二、对象的元数据

在JavaScript中,元数据是指与对象相关的数据,可以包含关于对象的类型、属性、方法等的信息。元数据不是对象的属性或方法,而是与对象相关联的数据。通过使用reflect-metadata库,可以在运行时动态地操作和获取对象的元数据,而不需要依赖于静态的类型系统。

元数据在JavaScript中通常使用对象属性的方式来实现。例如,可以使用以下方式添加和读取一个对象的元数据:

// 添加元数据
myObject.__metadata__ = {type: 'user', name: 'John'};// 读取元数据
console.log(myObject.__metadata__.type); // 'user'
console.log(myObject.__metadata__.name); // 'John'

在ES6及更高版本中,可以使用Reflect对象的metadata方法来获取和设置对象的元数据。例如:

// 添加元数据
Reflect.defineMetadata('type', 'user', myObject);
Reflect.defineMetadata('name', 'John', myObject);// 读取元数据
console.log(Reflect.getMetadata('type', myObject)); // 'user'
console.log(Reflect.getMetadata('name', myObject)); // 'John'

需要注意的是,元数据不是JavaScript标准的一部分,而是一个非正式的概念。

因此,需要使用第三方库(如reflect-metadata)来实现元数据的操作。同时,由于元数据不是JavaScript标准的一部分,因此它的使用方法和实现方式可能因库而异。

三、场景:依赖注入

import 'reflect-metadata';class Foo {}
class Bar {}class MyService {constructor(@Inject('foo') private foo: Foo,@Inject('bar') private bar: Bar,) {}
}function Inject(key: string) {return function(target: any, propertyKey: string, parameterIndex: number) {const metadata = Reflect.getMetadata('design:paramtypes', target, propertyKey);metadata[parameterIndex] = { key };Reflect.defineMetadata('design:paramtypes', metadata, target, propertyKey);};
}const myService = new MyService(new Foo(), new Bar());
const metadata = Reflect.getMetadata('design:paramtypes', myService, undefined);
console.log(metadata); // [ { key: 'foo' }, { key: 'bar' } ]

上面的代码中,我们定义了一个 MyService 类,并在其构造函数中使用 @Inject() 装饰器添加了元数据。在 Inject() 装饰器中,我们使用 Reflect.getMetadata() 获取到函数参数的元数据,然后修改其中的元素,将 key 信息添加到其中,最后使用 Reflect.defineMetadata() 将修改后的元数据重新设置到函数参数上。最终,我们使用 Reflect.getMetadata() 来读取 MyService 实例的元数据,并打印出结果。

四、场景:ORM(对象关系映射)

import 'reflect-metadata';class User {@Column()id: number;@Column()name: string;@Column()age: number;
}function Column() {return function(target: any, propertyKey: string) {const metadata = {type: Reflect.getMetadata('design:type', target, propertyKey),name: propertyKey,};Reflect.defineMetadata('column', metadata, target, propertyKey);};
}const metadata = Reflect.getMetadata('column', User.prototype, 'id');
console.log(metadata); // { type: Function, name: 'id' }

上面的代码中,我们定义了一个 User 类,并在其属性上使用 @Column() 装饰器添加了元数据。在 Column() 装饰器中,我们使用 Reflect.getMetadata() 获取到属性类型的元数据以及属性名称,然后将其封装为一个对象,并使用 Reflect.defineMetadata() 将其设置到属性上。最终,我们使用 Reflect.getMetadata() 来读取 User 类的 id 属性的元数据,并打印出结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/23329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT Prompt技术全攻略-入门篇:AI提示工程基础

系列篇章💥 No.文章1ChatGPT Prompt技术全攻略-入门篇:AI提示工程基础2ChatGPT Prompt技术全攻略-进阶篇:深入Prompt工程技术3ChatGPT Prompt技术全攻略-高级篇:掌握高级Prompt工程技术4ChatGPT Prompt技术全攻略-应用篇&#xf…

文献解读-肿瘤测序-第六期|《基于CRISPR/Cas9技术的肿瘤突变负荷测量新参考物质的开发》

关键词:肿瘤测序;基因组变异检测; 文献简介 标题(英文):Development of a Novel Reference Material for Tumor Mutational Burden Measurement Based on CRISPR/Cas9 Technolog标题(中文&…

【协同感知】Collaborative Perception in Autonomous Driving数据集与论文整理

Collaborative Perception in Autonomous Driving 目前最全的Collaborative Perception整理数据集协同感知论文-【三维目标检测】现实世界下的协同感知理想条件下的协同感知 目前最全的Collaborative Perception整理 https://github.com/Little-Podi/Collaborative_Perception…

【探索全球精彩瞬间,尽享海外短剧魅力!海外短剧系统,您的专属观影平台】

🌟 海外短剧系统,带您走进一个全新的视界,让您随时随地欣赏到来自世界各地的精选短剧。在这里,您可以感受到不同文化的碰撞,品味到各种题材的精髓,让您的生活更加丰富多彩! 🎬 精选…

HTML 基础操作知识

1.标题标签h1--h6,逐级缩小&#xff0c;双标记&#xff0c;属性&#xff1a;对其属性align 例&#xff1a;<h1 align"center">学雷锋&#xff0c;为人民服务</h1> 2.段落标签&#xff1a;p,双标记&#xff0c;属性:对其属性align …

【游戏】赚钱模拟器2.0版

赚钱模拟器2.0版出了&#xff01; int main(){p.rr(1000,1000,14).hide();//pen.button(id,string,col,size, dir,x,y,bgcol,edgecol);p.moveTo(0,100);p.button(0,"开始游戏",5,50,0,0,-200,1,5);pen.text("作者&#xff1a;小羊",5,50,0,0,-40,1);while…

跨语言系统中的功能通信:Rust、Java、Go和C++的最佳实践

在现代软件开发中&#xff0c;使用多种编程语言构建复杂系统已成为一种常见的做法。每种编程语言都有其独特的优势和适用场景&#xff0c;这使得在同一个系统中使用多种语言变得合理且高效。然而&#xff0c;这也带来了一个重要的挑战&#xff1a;如何在这些不同语言之间实现高…

【Python】【Pyinstaller】打包过程问题记录及解决

一、写在前面 将python脚本打包成.exe可执行文件&#xff0c;使用windows电脑运行。 所需库&#xff1a;pyinstaller 官网链接 命令格式&#xff1a; pyinstaller -F -w (需要打包的文件&#xff0c;文件名之间用空格分隔&#xff09;二、打包步骤&#xff08;见图片&#x…

自费出书一般需要多少钱?

自费出书的费用因多种因素而异&#xff0c;包括书号费、审稿费、排版费、封面设计费、纸张及印刷费、仓储物流费等。 以下是一些常见的费用项目和大致价格范围&#xff1a; - 书号费&#xff1a;书号是出版社的特有资源&#xff0c;书号费用在2023年又进一步上涨。目前&#…

Windows文件管理器导航窗口怎么删除第三方生成的无效导航【笔记】

Windows文件管理器导航窗口怎么删除第三方生成的无效导航【笔记】 导航窗口对应项目没有右击删除选项。 提示&#xff1a; 位置不可用 C:\Users\superman…不可用&#xff0c;如果该位置位于这台电脑上&#xff0c;请确保设备或驱动器连接&#xff0c;或者光盘已插入&#xf…

【恶补计算机基础】定点数和浮点数

在计算机中&#xff0c;小数点及其位置并不是显式表示出来的&#xff0c;而是隐含规定的。根据小数点的位置&#xff0c;可以分为两类&#xff1a;定点数和浮点数。 1 定点数 小数点的位置是固定不变的。根据小数点的具体位置&#xff0c;又可以分为两类&#xff1a;定点小数…

Python怎么hook:深入探索Python的Hook机制

Python怎么hook&#xff1a;深入探索Python的Hook机制 在Python编程中&#xff0c;hook&#xff08;钩子&#xff09;是一种强大的机制&#xff0c;它允许我们在不修改原有代码的情况下&#xff0c;对特定事件或函数调用的执行流程进行拦截和修改。然而&#xff0c;Python本身…

嵌入式笔试面试刷题(day17)

文章目录 前言一、单片机中断处理的流程是什么&#xff1f;二、进程间通信中使用锁和同步的目的是什么&#xff1f;三、define和const在内存占用上的差异是什么&#xff1f;#defineconst比较例子对比 四、波特率是什么&#xff0c;为什么双方波特率要相同&#xff0c;高低波特率…

上海市计算机学会竞赛平台2024年1月月赛丙组最大的和

题目描述 给定两个序列 &#x1d44e;1,&#x1d44e;2,…,&#x1d44e;&#x1d45b;a1​,a2​,…,an​ 与 &#x1d44f;1,&#x1d44f;2,…,&#x1d44f;&#x1d45b;b1​,b2​,…,bn​&#xff0c;请从这两个序列中分别各找一个数&#xff0c;要求这两个数的差不超过给…

JSP 中使用 (c 标签) c:if 标签进行 if/条件 判断

前言 JSTL全名为JavaServer Pages Standard Tag Library。JSTL是由JCP(Java Community Process)所制定的标准规范&#xff0c;它主要提供给Java Web开发人员一个标准通用的标签函数库。 想了解更多参考这里。 <c:if> 标签 <c:if> 标签是JSTL标签核心标签之一 …

Linux-vi编辑器命令使用

一、初始-vi 1、 vi-打开文件并且定位行 有可能会遇到打开一个文件&#xff0c;并定位到指定行的情况 例如&#xff0c;知道某一行代码有错误&#xff0c;可以快速定位到出错代码的位置 可以使用以下命令打开文件$ vi 文件名 行数 提示&#xff1a;如果只带上 而不指定行号&…

Windows API 使用 SetTimer 定时器来持续画图

在Windows API中&#xff0c;SetTimer 函数用于在指定的窗口上设置一个定时器。当定时器到期时&#xff0c;窗口会收到一个WM_TIMER消息。以下是SetTimer函数的详细解释和用法&#xff1a; 函数原型 UINT_PTR SetTimer(HWND hWnd, // 窗口句柄UINT_PTR n…

Python邮件群发有哪些步骤?如何批量发送?

Python邮件群发的注意事项&#xff1f;怎么使用Python群发邮件&#xff1f; 使用Python进行邮件群发&#xff0c;不仅可以自动化流程&#xff0c;还可以节省大量的时间和精力。AokSend将详细介绍使用Python进行邮件群发的步骤&#xff0c;并在过程中提供实用的建议和注意事项。…

windows下使用命令清空U盘

1、CMD命令打开后输入diskpart命令打开磁盘分区管理工具 diskpart打开如下窗口 Microsoft DiskPart 版本 10.0.19041.3636 Copyright (C) Microsoft Corporation. 在计算机上: DESKTOP-TR9HQRP 2、输入查看所有磁盘命令 list disk打印如下windows 磁盘 ###  状态    …

机械臂码垛机:解读其高效作业与灵活性

在当今高度自动化的工业时代&#xff0c;机械臂码垛机以其高效作业和灵活性&#xff0c;成为了生产线上的得力助手。这款设备不仅大幅提升了生产效率&#xff0c;还显著降低了人工操作的强度和风险&#xff0c;为现代工业发展注入了强大的动力。 机械臂码垛机的高效作业能力令人…