Typescript装饰器浅析

网络维
• 阅读 2086

介绍

随着TypeScript和ES6里引入了类,在一些场景下我们需要额外的特性来支持标注或修改类及其成员。 装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。 Javascript里的装饰器目前处在 建议征集的第二阶段,但在TypeScript里已做为一项实验性特性予以支持。

使用

命令行:

tsc --target ES5 --experimentalDecorators

tsconfig.json:

{
    "compilerOptions": {
        "target": "ES5",
        "experimentalDecorators": true
    }
}

装饰器定义

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

基础使用

target指向的是HelloWordClass
function helloWord(target: any) {
    console.log('hello Word!');
}

@helloWord
class HelloWordClass {

}
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;
};
function helloWord(target) {
    console.log('hello Word!');
}
var HelloWordClass = /** @class */ (function () {
    function HelloWordClass() {
    }
    HelloWordClass = __decorate([
        helloWord
    ], HelloWordClass);
    return HelloWordClass;
}());

这是编译过后的代码,是声明一个__decorate,把HelloWordClass传给前面的fn数组

类装饰器

应用于类构造函数,其参数是类的构造函数。

function addAge(args: number) {
    return function (target: Function) {
        target.prototype.age = args;
    };
}

@addAge(18)
class Hello {
    name: string;
    age: number;
    constructor() {
        console.log('hello');
        this.name = 'yugo';
    }
}

console.log(Hello.prototype.age);//18
let hello = new Hello();

console.log(hello.age);//18

方法装饰器

它会被应用到方法的 属性描述符上,可以用来监视,修改或者替换方法定义。
方法装饰会在运行时传入下列3个参数:

1、对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、成员的名字。
3、成员的属性描述符{value: any, writable: boolean, enumerable: boolean, configurable: boolean}。

function addAge(constructor: Function) {
  constructor.prototype.age = 18;
}
​
function method(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
   console.log(target);
   console.log("prop " + propertyKey);
   console.log("desc " + JSON.stringify(descriptor) + "\n\n");
};
​
@addAge
class Hello{
  name: string;
  age: number;
  constructor() {
    console.log('hello');
    this.name = 'yugo';
  }
​
  @method
  hello(){
    return 'instance method';
  }
​
  @method
  static shello(){
    return 'static method';
  }
}

访问器装饰器

访问器装饰器应用于访问器的属性描述符,可用于观察,修改或替换访问者的定义。 访问器装饰器不能在声明文件中使用,也不能在任何其他环境上下文中使用(例如在声明类中)。

 class Point {
    private _x: number;
    private _y: number;
    constructor(x: number, y: number) {
        this._x = x;
        this._y = y;
    }

    @configurable(false)
    get x() { return this._x; }

    @configurable(false)
    get y() { return this._y; }
}

方法参数装饰器

参数装饰器表达式会在运行时当作函数被调用

const parseConf = [];
class Modal {
    @parseFunc
    public addOne(@parse('number') num) {
        console.log('num:', num);
        return num + 1;
    }
}

// 在函数调用前执行格式化操作
function parseFunc(target, name, descriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
        for (let index = 0; index < parseConf.length; index++) {
            const type = parseConf[index];
            console.log(type);
            switch (type) {
                case 'number':
                    args[index] = Number(args[index]);
                    break;
                case 'string':
                    args[index] = String(args[index]);
                    break;
                case 'boolean':
                    args[index] = String(args[index]) === 'true';
                    break;
            }
            return originalMethod.apply(this, args);
        }
    };
    return descriptor;
}

// 向全局对象中添加对应的格式化信息
function parse(type) {
    return function (target, name, index) {
        parseConf[index] = type;
        console.log('parseConf[index]:', type);
    };
}
let modal = new Modal();
console.log(modal.addOne('10')); // 11

属性装饰器

属性装饰器表达式会在运行时当作函数被调用,

function log(target: any, propertyKey: string) {
    let value = target[propertyKey];
    // 用来替换的getter
    const getter = function () {
        console.log(`Getter for ${propertyKey} returned ${value}`);
        return value;
    }
    // 用来替换的setter
    const setter = function (newVal) {
        console.log(`Set ${propertyKey} to ${newVal}`);
        value = newVal;
    };
    // 替换属性,先删除原先的属性,再重新定义属性
    if (delete this[propertyKey]) {
        Object.defineProperty(target, propertyKey, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
    }
}
class Calculator {
    @log
    public num: number;
    square() {
        return this.num * this.num;
    }
}
let cal = new Calculator();
cal.num = 2;
console.log(cal.square());
// Set num to 2
// Getter for num returned 2
// Getter for num returned 2
// 4
https://www.jianshu.com/p/afe...
https://www.tslang.cn/docs/ha...
点赞
收藏
评论区
推荐文章
皮卡皮卡皮 皮卡皮卡皮
4年前
了解什么是 TypeScript
内容纲要了解什么是TypeScriptTypeScript基本语法TypeScript介绍TypeScript是什么TypeScript是JavaScript的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的JavaScript代码。由于最终在浏览器中运行的仍然是JavaScript,所以TypeScript并
Irene181 Irene181
4年前
恶补了 Python 装饰器的六种写法,你随便问~
大家好,我是明哥。今天给大家分享一下关于装饰器的知识点,内容非常干,全程高能,认真吸收看完,一定会对装饰器有更深的理解。Hello,装饰器装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰
Stella981 Stella981
3年前
GitHub上的7个热门TypeScript项目,要不要学一下呢?
TypeScript是JavaScript的一个超集,支持ECMAScript6标准(ES6教程)由微软开发的自由和开源的编程语言。设计目标是开发大型应用,它可以编译成纯JavaScript,编译出来的JavaScript可以运行在任何浏览器上。语言特性TypeScript是一种
Easter79 Easter79
3年前
TypeScript 教程
TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。安德斯·海尔斯伯格,C的首席架构师,已工作于TypeScript的开发。\1\TypeScript扩展了JavaScript的句法,所以任何现有的JavaScript程序可以不
Wesley13 Wesley13
3年前
ES6 系列之我们来聊聊装饰器
_摘要:_ Decorator装饰器主要用于:1.装饰类2.装饰方法或属性装饰类\\\js@annotation(https://my.oschina.net/annotation)classMyClass{}functionannotation(target){target.annotatedt
Stella981 Stella981
3年前
Python之路(第二十八篇) 面向对象进阶:类的装饰器、元类
一、类的装饰器类作为一个对象,也可以被装饰。例子defwrap(obj):print("装饰器")obj.x1obj.y3obj.z5returnobj​
Easter79 Easter79
3年前
TypeScript基础入门之装饰器(三)
转载 TypeScript基础入门之装饰器(三)(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.gowhich.com%2Fblog%2F956)继续上篇文章\TypeScript基础入门之装饰器(二)(https://www.oschina.net/action/G
Stella981 Stella981
3年前
Python进阶笔记(2)
'''装饰器装饰器(Decorators)是Python的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短。如果已经接触过FLASK的,想想路由功能。如果没有接触过FLASK的,建议学习下。''''''各种推导式(compre
Stella981 Stella981
3年前
Python装饰器用法实例总结
一、装饰器是什么python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。简单的说装饰器就是一个用来返回函数的函数。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离
3A网络 3A网络
2年前
Golang 常见设计模式之装饰模式
Golang常见设计模式之装饰模式想必只要是熟悉Python的同学对装饰模式一定不会陌生,这类Python从语法上原生支持的装饰器,大大提高了装饰模式在Python中的应用。尽管Go语言中装饰模式没有Python中应用的那么广泛,但是它也有其独到的地方。接下来就一起看下装饰模式在Go语言中的应用。简单装饰器我们通过一个简单的例子来
GeorgeGcs GeorgeGcs
1天前
【HarmonyOS 5】鸿蒙的装饰器原理和自定义装饰器
鸿蒙开发能力HarmonyOSSDK应用服务鸿蒙金融类应用(金融理财一、鸿蒙中的装饰器是什么?在ArkTS中装饰器(Decorator)是一种特殊的声明,能够对类、方法、属性等进行标注和修改。因为ArkTS是TypeScript扩展而来的编程语言,Type
网络维
网络维
Lv1
时间好比一面战鼓,它能激励我们加快前进的脚步。
文章
6
粉丝
0
获赞
0