李恒道 发表于 2022-8-9 19:04:17

typescript装饰器原理

装饰器会调用
```
Foo = __decorate([
    Cls(),
    __param(0, Param()),
    __metadata("design:paramtypes", )
], Foo);
```
之类的代码
我们来研究一下decorate的作用
总体代码如下
```
var __decorate =
(this && this.__decorate) ||
function (decorators, target, key, desc) {
    var c = arguments.length,
      r =
      c < 3
          ? target
          : desc === null
          ? (desc = Object.getOwnPropertyDescriptor(target, key))
          : desc,
      d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
      r = Reflect.decorate(decorators, target, key, desc);
    else
      for (var i = decorators.length - 1; i >= 0; i--)
      if ((d = decorators))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
```
先来看开头
```
(this && this.__decorate)
```
判断this以及this下是否存在,如果存在则直接继承,不存在则赋值函数
函数传参四个
function (decorators, target, key, desc)
装饰器,目标对象,key值,描述符
然后再看一句
```
    var c = arguments.length,
      r =
      c < 3
          ? target
          : desc === null
          ? (desc = Object.getOwnPropertyDescriptor(target, key))
          : desc,
      d;
```

c为参数长度,r来根据c来判断
如果c小于3
则为target
如果描述符不为空,则为自身,否则则为取描述符
这里大概可以看出来选项有三种,对象,描述符,自身
应该是要设置的位置
声明了一个d,没有赋值
```
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
      r = Reflect.decorate(decorators, target, key, desc);
    else
      for (var i = decorators.length - 1; i >= 0; i--)
      if ((d = decorators))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
```
判断是否有Reflect.decorate函数,如果没有则我们自己执行循环,有则直接传入
```
      for (var i = decorators.length - 1; i >= 0; i--)
      if ((d = decorators))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
```
遍历装饰器数组
从后向前遍历
判断每个装饰器赋值给d并是否不为空
如果不为空则调用
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key))
这里可以看到是根据传入的参数来传入不同的内容
如果小于3则只传入对象r,大于三传入目标对象,key,r,否则传入目标对象,key
我们对比官方文档以及林不渡的TypeScript 全面进阶指南
可以知道
**类装饰器**是一个对象,传入一个类
**方法装饰器**三个对象,原型,方法名,属性描述符
**访问符装饰器**三个对象,原型,方法名,属性描述符
**属性装饰器**两个对象,原型,属性名
**参数装饰器**三个对象,原型,参数名,索引值
因为我们还需要传入装饰器
也就是说
类2个
方法4个
访问符4个
装饰器3个
参数4个
对比这里
【小于3则只传入对象r】(指代类装饰器,传入类)
【大于三传入目标对象,key,r】(指代原型,名字,描述符/索引值)
【否则传入目标对象,key 】指代属性装饰器的原型和属性名
那我们就可以知道r分为类、描述符、index
最后调用
    return c > 3 && r && Object.defineProperty(target, key, r), r;
判断是否是四个参数,如果是则定义一下,然后返回r
# 结束
撒花~



页: [1]
查看完整版本: typescript装饰器原理