Typescript中的装饰器原理

Posted yangyangxxb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Typescript中的装饰器原理相关的知识,希望对你有一定的参考价值。

Typescript中的装饰器原理

1、小原理

  因为react中的高阶组件本质上是个高阶函数的调用,

  所以高阶组件的使用,我们既可以使用函数式方法调用,也可以使用装饰器。

  也就是说,装饰器的本质就是一个高阶函数,

  就是利用TypeScript的弱类型特性和装饰器特性,实现了一个加强版。

 


 

 

2、以一个例子来讲

    
//定义一个装饰器函数decTest
      
    function decTest(constructor: Function) {
        console.log(constructor("hello!"));
    }
    
//在类Greeter上安装decTest装饰器

    @decTest

    class Greeter {
        greeting: string;
        constructor(message: string) {
            this.greeting = message;
            console.log("in constructor:",message);
        }
        greet() {
            return "Hello, " + this.greeting;
        }
    }
        

  编译后:

//第一行定义了一个_decarate函数,这个函数会处理类装饰器的功能

//第18行可以看出,调用_decorate函数时只给了两个参数,
//一个是数组,其中包含多个类装饰器,这里只使用了一个装饰器
//另一个是Greeter类的构造函数Greeter()
//调用__decorate函数时decorators为一个装饰器数组;
//target为构造函数Greeter(),
//key和desc均未使用,值为undefined。 
//这里的__decorate函数为各种装饰器的通用代码,
//在方法装饰器中key和desc均有使用。

1.    var __decorate = (this && this._decorate) || function (decorators, target, key, desc) {

//第2行参数数量在类装饰器中为2,显然小于3。

2.        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;

//第3行指出如果系统支持反射,
//则直接使用Reflect.decorate(decorators,target, key, desc)方法。
//否则自行定义实现装饰器机制的代码。

3.        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4.        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;
5.        return c > 3 && r && Object.defineProperty(target, key, r), r;
6.    };
7.    function decTest(constructor) {
8.        console.log(constructor("hello!"));
9.    }

//定义了一个函数,从第22行可以看出,这个函数是自调用的

10.    var Greeter = (function () {
11.        function Greeter(message) {
12.            this.greeting = message;
13.            console.log("in constructor:", message);
14.        }
15.        Greeter.prototype.greet = function () {
16.            return "Hello, " + this.greeting;
17.        };

//18行的时候函数调用了_decorate函数

18.        Greeter = __decorate([
19.            decTest
20.        ], Greeter);
21.        return Greeter;
22.    }());

  简化:

1.    var __decorate = function (decorators, target, key, desc) {
2.        r = target;

//可以看出第三行实现了装饰器的堆叠
//堆叠的规则是先处理后面的,
//再处理前面的

3.        for (var i = decorators.length - 1; i >= 0; i--)
4.            if (d = decorators[i]) r = d(r);
5.        return r;
6.    };
7.    
8.    function decTest(constructor) {
9.        console.log(constructor("hello!"));
10.    }

//这个方法最后返回一个Greeter,改造后的Greeter

11.    var Greeter = (function () {
12.        function Greeter(message) {
13.            this.greeting = message;
14.            console.log("in constructor:", message);
15.        }
16.        Greeter.prototype.greet = function () {
17.            return "Hello, " + this.greeting;
18.        };

//第19行实际上就是通过类装饰器函数修改了Greeter类的构造函数Greeter(message)的行为,
//从而修改了对象的特性,
//比如增加接口,注入类成员……等等。

19.        Greeter = __decorate([
20.            decTest
21.        ], Greeter);
22.        return Greeter;
23.    }());

 

 

以上。

以上是关于Typescript中的装饰器原理的主要内容,如果未能解决你的问题,请参考以下文章

Typescript 中的装饰器返回函数的时间

细说Typescript中的装饰器

C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗

TypeScript装饰器

TypeScript 素描 - 装饰器

关于何时在 TypeScript 中调用装饰器的困惑