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.    }());

 

 

以上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM