zoukankan      html  css  js  c++  java
  • 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.    }());

    以上。

  • 相关阅读:
    Unicode详解
    VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏
    关于MFC下检查和消除内存泄露的技巧
    ASCII 、GB2312、GBK、GB18030、unicode、UTF8字符集编码详解
    A note from UrlEscape Function
    Unicode和UTF8之间的转换详解
    Base64编码
    全面解读WM_NOTIFY
    关于URL编码
    URL的#号
  • 原文地址:https://www.cnblogs.com/yangyangxxb/p/10105379.html
Copyright © 2011-2022 走看看