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


    (1)前言

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

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

    (2)元数据

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

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

        做过网站SEO优化的同学都知道,HTML有一个文档级元数据元素,而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)有一腿。

  • 相关阅读:
    openstack计算节点的虚机部署安装
    计算机组成原理学习笔记:计算机的性能指标
    wxPython 之 wxAuiManage实现停靠(悬停)子窗口
    代码随想录 -- day60 -- 84.柱状图中最大的矩形
    vuex状态管理(二)超级详细使用教程(包含辅助函数map的使用),一看就会,一学就懂
    Intel芯片的Mac电脑需注意,新型恶意软件能窃取系统中的各类密码
    Redis——Linux下安装以及命令操作
    海栎创原厂HAA9806和HAA9806-R连续10W输出功率的单声道音频功率放大器
    汇总selenium利用xpath等找网页节点的方法(二)
    CoreDNS篇9-kubernetes插件
  • 原文地址:https://blog.csdn.net/qq_41308489/article/details/127723669