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