上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

typescript装饰器原理

[复制链接]
  • TA的每日心情
    慵懒
    2024-10-28 07:07
  • 签到天数: 193 天

    [LV.7]常住居民III

    712

    主题

    5992

    回帖

    6780

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6780

    荣誉开发者喜迎中秋油中2周年生态建设者

    发表于 2022-8-9 19:04:17 | 显示全部楼层 | 阅读模式

    装饰器会调用

    Foo = __decorate([
        Cls(),
        __param(0, Param()),
        __metadata("design:paramtypes", [String])
    ], 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[i]))
              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[i]))
              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[i]))
              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

    结束

    撒花~

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表