作为程序员听过《元宇宙》,那你听过《元编程》吗?

(1)前言

    最近,在排查项目上的一些权限问题,碰到了nest.js的一个API:"setMetaData" 。它是一个设置元数据(metadata)的装饰器。为了搞明白,设置后的元数据是在哪个地方。我便去翻了一下"setMetaData"的源码。看完源码后,便接触到了 元数据 和 元编程(metaprogramming)。

那么,什么是元数据?什么是元编程呢?

(2)元数据

    在日常生活中,元数据是无所不在的。我在阮一峰大神的博客下看到这么一句描述:"元数据是用来描述数据的数据(Data that describes other data)" 。我们可以通过生活中的场景来认识它。平时观看一部电影时,我们在看电影的简介时,而"简介"它就是元数据。 也可以用我们自身来描述元数据,每个人都有"姓名"、"年龄"、"身高"、"性格"等, 而这些就是元数据。

    而在程序中,我们也可以把生活看成一个数据库。而姓名是我们数据库表里的"name"字段。而"name"它便是元数据。

    做过网站SEO优化的同学都知道,HTML有一个<meta>文档级元数据元素,而keywords是经常被用于提高网站的SEO的元数据,搜索引擎会根据keywords关键词去归因。

(3)元编程

    "元编程能让你拥有可以扩展程序自身能力"。元编程可以让你修改程序的底层运行的规则,同时可以拓展和更好的维护程序。

    ES6之后引入了一些常见的元编程有:Proxy、Reflect、Symbol等。在我们平时编程,常用Proxy结合Reflect去进行控制程序的运行规则。

   如我们所见的Vue3.0通过结合Proxy和Reflect去代理对象和反射对象来实现响应式原理。看到这,相信大家对元数据和元编程有一定的理解了,接下来通过nest.js的源码展开。

(4)Reflect Metadata

    以下是nest.js设置元数据的业务场景:

    接下来我们从nest.js源码来分析setMetadata是怎么实现的。

    采用Reflect.defineMetadata去定义一个元数据。而Reflect.defineMetadata 是 Reflect Metadata的方法。

Reflect Metadata是15年的一个提案,如果要用Reflect Metadata就要借助三方包(reflect-metadata)。我们需要去安装一下该npm包:

    TS环境已经实现了@Reflect.metadata装饰器,我们通过创建index.ts文件编译一个例子。

    用tsc去编译一下之后可以得到后的index.js,已经有了我们定义的元数据。

 但是tsc编译选项可以通过开启emitDecoratorMetadata就可以自动添加一些元数据。因为Reflect.metadata还是草案阶段,所以还需要开启另一个选项experimentalDecorators。

    编译后的结果多了三条元数据,分别是目标的类型、目标的参数类型、目标的返回值类型。

    在nest.js的setMetadata的实现核心就是Reflect metadata的API。

    setMetadata中的Reflect.defineMetadata就是定义一个元数据,元数据设置后是存在的目标上,也就是类,或者对象上。

    设置元数据后的对象上都会存在 [[Metadata]]属性,该属性是一个 Map 对象。因为Reflect Metadata源码上采用的数据结构是WeakMap。主要是WeakMap不增加引用计数(垃圾回收的一种方式)的特点。

而更多的Reflect Metadata的方法可以直接看文档。

Metadata Proposal - ECMAScript

(5)小结

  1. nest.js的setMetadata装饰器实现原理是Reflect Metadata。设置后的元数据是存在类或者对象上。

   2. nest.js的Controller、Module、Service等一些装饰器都是通过Reflect Metadata给类和对象添加元数据,然后初始化时取出元数据做依赖扫描,实例化后放到IOC的容器里。

  最后你会发现,实现nest.js的原理和元数据(metadata)、元编程(metaprogramming)有一腿。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值