Skip to main content

核心原理

Nest.js 的核心原理其实就是通过装饰器给 class 或者对象添加元数据,然后初始化的时候取出这些元数据,进行依赖的分析,然后创建对应的实例对象就可以了。它的核心就是 IOC 容器,也就是自动扫描依赖,创建实例对象并且自动依赖注入。Nest 的 Controller、Module、Service 等等所有的装饰器都是通过 Reflect.meatdata 给类或对象添加元数据的,然后初始化的时候取出来做依赖的扫描,实例化后放到 IOC 容器里。

这个核心原理其实和springBoot差不多, 也是扫描装饰器 这些所谓框架的原理都是所谓的元编程

我们需要知道两个比较新的特性:

  • 装饰器
  • Reflect.meatdata

这第一篇先来搞懂装饰器。

TypeScript 是这样描述装饰器的:

  • 装饰器提供了一种为类声明和成员添加注解元编程语法的方法。
  • 装饰器是一种特殊类型的声明,可以附加到类声明方法访问器属性参数。装饰器使用 形式@expression,其中expression必须求值为将在运行时调用的函数,其中包含有关装饰声明的信息。

装饰器本质

装饰器本质上是一种特殊的函数被应用在于:

  1. 类属性
  2. 类方法
  3. 类访问器
  4. 类方法的参数(在 TypeScript 5.x 中不再包含)

一句话:装饰器就是一个接收特定参数的函数,使用@函数名可以对一些类,属性,方法等进行装饰来实现一些 运行时 的 hook 拦截机制。

元编程

在一些装饰器的教程中,通常会遇到一个名词:元编程。什么是元编程?比较晦涩难懂的说法是:

我们不编写处理用户数据的代码(编程)。 我们编写的代码是处理用户数据的代码(元编程)。

通俗来讲:元编程 (meta-programming) 是通过操作 程序实体 (program entity),在 编译时 (compile time) 计算出 运行时 (runtime) 需要的常数、类型、代码的方法。它的诞生是源于:需要非常灵活的代码来适应快速变化的需求,同时保证性能。 与一般代码的区别是:

一般代码的操作对象是数据。 元编程的操作对象是代码:code as data。 如果编程的本质是抽象,那么元编程就是更高层次的抽象。

注意事项

需要注意的是,在 TypeScript 5.x 之前,装饰器还只是作为一个实验性功能,使用时需要在tsconfig.json 中开启以下配置:

json

复制代码

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

从 v5.0 开始,不需要此设置,默认情况下可以使用 stage 3 的装饰器。

  • 第一个,experimentalDecorators打开装饰器支持。
  • 第二个,emitDecoratorMetadata,发出包所需的数据reflect-metadata。这个包使我们能够通过记录有关类、属性、方法和参数的元数据,在装饰器中做一些更强大的事情。

 带参数的类装饰器

装饰器也可以接受参数,这需要遵循一种不同的模式,即装饰器工厂。下面是一个简单的类装饰器示例,它不仅展示了如何传递参数,还帮助我们理解了使用多个装饰器时的执行顺序。

function withParam(path: string) {
console.log(`outer withParam ${path}`);
return (target: Function) => {
console.log(`inner withParam ${path}`);
};
}

@withParam('first')
@withParam('middle')
@withParam('last')
class ExampleClass {
// ...
}


在这个示例中,我们加了三次 withParam,打印出的信息是:

yaml

复制代码

%% 工厂函数是自上而下执行的 %%
outer withParam first
outer withParam middle
outer withParam last

%% 装饰器函数则是自下而上执行的 %%
inner withParam last
inner withParam middle
inner withParam first

记住,工厂函数是自上而下执行的,而装饰器函数则是自下而上执行的。

TMD 就不能搞成顺序都是从上往下吗,尼玛的

https://juejin.cn/post/7265528564437631010