TypeScript躬行记(8)——装饰器

2023-12-25 17:48
文章标签 typescript 装饰 躬行

本文主要是介绍TypeScript躬行记(8)——装饰器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  装饰器(Decorator)可声明在类及其成员(例如属性、方法等)之上,为它们提供一种标注,用于分离复杂逻辑或附加额外逻辑,其语法形式为@expression。expression是一个会在运行时被调用的函数,它的参数是被装饰的声明信息。假设有一个@sealed装饰器,那么可以像下面这样定义sealed()函数。

function sealed(target) {//...
}

  有两种方式可以开启装饰器,第一种是在输入命令时添加--experimentalDecorators参数,如下所示,其中--target参数不能省略,它的值为“ES5”。

tsc default.ts --target ES5 --experimentalDecorators

  第二种是在tsconfig.json配置文件中添加experimentalDecorators属性,如下所示,对应的target属性也不能省略。

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

一、类装饰器

小说阅读网 www.7wx.org

  类装饰器用于监听、修改或替换类的构造函数,并将其作为类装饰器唯一可接收的参数。当装饰器返回undefined时,延用原来的构造函数;而当装饰器有返回值时,会用它来覆盖原来的构造函数。下面的示例会通过类装饰器封闭类的构造函数和原型,其中@sealed声明在类之前。

@sealed
class Person {name: string;constructor(name: string) {this.name = name;}
}
function sealed(constructor: Function) {Object.seal(constructor);Object.seal(constructor.prototype);
}

  在经过TypeScript编译后,将会生成一个__decorated()函数,并应用到Person类上,如下所示。

var Person = /** @class */ (function() {function Person(name) {this.name = name;}Person = __decorate([sealed], Person);return Person;
})();

  注意,类装饰器不能出现在.d.ts声明文件和外部类之中。

二、方法装饰器

  方法装饰器声明在类的方法之前,作用于方法的属性描述符,比类装饰器还多一个重载限制。它能接收三个参数,如下所列:

  (1)对于静态成员来说是类的构造函数,而对于实例成员则是类的原型对象。

  (2)成员的名字,一个字符串或符号。

  (3)成员的属性描述符,当输出版本低于ES5时,该值将会是undefined。

  当方法装饰器返回一个值时,会覆盖当前方法的属性描述符。下面是一个简单的例子,方法装饰器的第一个参数是Person.prototype,第二个是“cover”,调用getName()方法得到的将是“freedom”,而不是原先的“strick”。

class Person {@covergetName(name) {return name;}
}
function cover(target: any, key: string, descriptor: PropertyDescriptor) {descriptor.value = function() {return "freedom";};return descriptor;
}
let person = new Person();
person.getName("strick");        //"freedom"

三、访问器装饰器

  访问器装饰器声明在类的访问器属性之前,作用于相应的属性描述符,其限制与类装饰器相同,而接收的三个参数与方法装饰器相同。并且还需要注意一点,TypeScript不允许同时装饰一个成员的get和set访问器,只能应用在第一个访问器上。

  以下面的Person类为例,定义了一个访问器属性name,当访问它时,得到的将是“freedom”,而不是原先的“strick”。

class Person {private _name: string;@accessget name() {return this._name;}set name(name) {this._name = name;}
}
function access(target: any, key: string, descriptor: PropertyDescriptor) {descriptor.get = function() {return "freedom";};return descriptor;
}
let person = new Person();
person.name = "strick";
console.log(person.name);        //"freedom"

四、属性装饰器

  属性装饰器声明在属性之前,其限制与访问器装饰器相同,但只能接收两个参数,不存在第三个属性描述符参数,并且没有返回值。仍然以下面的Person类为例,定义一个name属性,并且在@property装饰器中修改其值。

class Person {@propertyname: string;
}
function property(target: any, key: string) {Object.defineProperty(target, key, {value: "freedom"});
}
let person = new Person();
person.name = "strick";
console.log(person.name);        //"freedom"

五、参数装饰器

  参数装饰器声明在参数之前,它没有返回值,其限制与方法装饰器相同,并且也能接收三个参数,但第三个参数表示装饰的参数在函数的参数列表中所处的位置(即索引)。下面用一个例子来演示参数装饰器的用法,需要与方法装饰器配合。

let params = [];
class Person {@funcgetName(@required name) {return name;}
}

  在@func中调用getName()方法,并向其传入params数组中的值,@required用于修改指定位置的参数的值,如下所示。

function func(target: any, key: string, descriptor: PropertyDescriptor) {const method = descriptor.value;descriptor.value = function () {return method.apply(this, params);};return descriptor;
}
function required(target: any, key: string, index: number) {params[index] = "freedom";
}

  当实例化Person类,调用getName()方法,得到的将是“freedom”。

let person = new Person();
person.getName("strick");        //"freedom"

六、装饰器工厂

  装饰器工厂是一个能接收任意个参数的函数,用来包裹装饰器,使其更易使用,它能返回上述任意一种装饰器函数。接下来改造方法装饰器一节中的cover()函数,接收一个字符串类型的value参数,返回一个方法装饰器函数,如下所示。

function cover(value: string) {return function(target: any, key: string, descriptor: PropertyDescriptor) {descriptor.value = function() {return value;};return descriptor;};
}

  在将@cover作用于类中的方法时,需要传入一个字符串,如下所示。

class Person {@cover("freedom")getName(name) {return name;}
}

七、装饰器组合

  将多个装饰器应用到同一个声明上时,既可以写成一行,也可以写成多行,如下所示。

/****** 一行 ******/
@first @second desc
/****** 多行 ******/
@first 
@second
desc

  这些装饰器的求值方式与复合函数类似,先由上至下依次执行装饰器,再将求值结果作为函数,由下至上依次调用。例如定义两个装饰器工厂函数,如下代码所示,在函数体和返回的装饰器中都会打印一个数字。

function first() {console.log(1);return function(target: any, key: string, descriptor: PropertyDescriptor) {console.log(2);};
}
function second() {console.log(3);return function(target: any, key: string, descriptor: PropertyDescriptor) {console.log(4);};
}

  将它们先后声明到类中的同一个方法,如下代码所示。根据求值顺序可知,先打印出1和3,再打印出4和2。

class Person {@first()@second()getName(name) {return name;}
}

 

这篇关于TypeScript躬行记(8)——装饰器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/536384

相关文章

Python中的属性装饰器:解锁更优雅的编程之道

引言 在Python的世界里,装饰器是一个强大的工具,它允许我们以一种非侵入性的方式修改函数或方法的行为。而当我们谈论“属性装饰器”时,则是在探讨如何使用装饰器来增强类中属性的功能。这不仅让我们的代码更加简洁、易读,同时也提供了强大的功能扩展能力。本文将带你深入了解属性装饰器的核心概念,并通过一系列实例展示其在不同场景下的应用,从基础到进阶,再到实际项目的实战经验分享,帮助你解锁Python编程

python+selenium2学习笔记unittest-04装饰器skip用法

在运行测试用例时,有时需跳过或判断用例时,可以用装饰器来实现 主要的几个方法就是下面的这几种 import unittestclass test(unittest.TestCase):def setUp(self):pass@unittest.skip('跳过')def test_01(self):print("直接跳过")@unittest.skipIf(3>2,'当条件为TRUE跳过')

python内置装饰器@staticmethod,@classmethod

2.@staticmethod,@classmethod 有了@property装饰器的了解,这两个装饰器的原理是差不多的。@staticmethod返回的是一个staticmethod类对象,而@classmethod返回的是一个classmethod类对象。他们都是调用的是各自的__init__()构造函数。 一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。 而使用@stat

创建 typescript 项目.md

有时候需要创建一个最简单的 typescript 项目来验证一些东西,这里记录一下如何创建一个最简单的 typescript 项目。 创建并初始化项目 $ mkdir my-typescript-project$ cd my-typescript-project$ npm init -y$ npm install typescript ts-node @types/node --save

Python中的装饰器及其应用场景

Python中的装饰器(Decorators)是一个非常强大且优雅的特性,它允许你在不修改原有函数或类定义的情况下,给函数或类增加新的功能。装饰器本质上是一个函数,它接收一个函数(或类)作为参数,并返回一个新的函数(或类),这个新函数(或类)会包含原函数(或类)的所有功能,并在其基础上增加额外的功能。装饰器的这种特性使得代码的重用性、可读性和可维护性都得到了极大的提升。 一、装饰器的基本概念

七、装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,允许在不改变对象自身的情况下,动态地向对象添加新功能。它通过将功能附加到对象的方式来增强其行为,提供了一种灵活的替代方案来使用子类扩展功能。 主要组成部分: 抽象构件(Component): 定义一个接口或抽象类,声明了要装饰的对象的基本功能。 具体构件(ConcreteComponent): 实现抽象构件的具体类,是

java设计模式day03--(结构型模式:代理模式、适配器模式、装饰者模式、桥接模式、外观模式、组合模式、享元模式)

5,结构型模式 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: 代理模式 适配器模式 装饰者模式 桥接模式 外观模式 组合模式

TypeScript数据结构与算法系列(一) —— 链表

TypeScript目录 链表常用操作1.初始化链表2. 插入节点3. 删除节点4. 访问节点5. 查找节点 图源:你好算法 内存空间是所有程序的公共资源,在一个复杂的系统运行环境下,空闲的内存空间可能散落在内存各处。我们知道,存储数组的内存空间必须是连续的,而当数组非常大时,内存可能无法提供如此大的连续空间。此时链表的灵活性优势就体现出来了。 链表(linked list)

VueSax-解决Vue3报错问题,并支持typescript

以下为坑点 根据官方提示,本人在vue3+typescript的项目中添加了vuesax的组件依赖 根据正常的导入依赖思路编写代码,发现typescript一直报 查询vuesax的目录文件发现存在ts文件,于是乎觉得是自己的问题,就查阅gpt与网上资料,查了一晚上加入各种方法,都没有解决,于是乎选择javascript进行测试,发现还是不行! js里虽然不报错,但是在页面

js装饰器简单理解

装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类方法。 装饰器是一种函数,写成@函数名。它可以放在类和类方法的定义前面。如下: @frozenclass Foo {@configurable(false)@enumerable(true)method() {}@throttle(500)expensiveMethod() {}} 上面代