首页 > 其他分享 >TS装饰器,我们来单独聊聊其特性以及提出时间

TS装饰器,我们来单独聊聊其特性以及提出时间

时间:2024-11-09 15:44:01浏览次数:3  
标签:function console log TS Person 聊聊 装饰 target

目录
在这里插入图片描述

⼀、简介

1、装饰器本质是⼀种特殊的函数,它可以对:类、属性、⽅法、参数进⾏扩展,同时能让代码更简洁。
2. 装饰器⾃ 2015 年在 ECMAScript-6 中被提出到现在,已将近10
3. 截⽌⽬前,装饰器依然是实验性特性 ,需要开发者⼿动调整配置,来开启装饰器⽀持
4. 装饰器有 5

1.类装饰器
2.属性装饰器
3.⽅法装饰器
4.访问器装饰器
5.参数装饰器

备注:虽然TypeScript5.0中可以直接使⽤类装饰器,但为了确保其他装饰器可⽤,现阶
段使⽤时,仍建议使⽤experimentalDecorators配置来开启装饰器⽀持,⽽且不排除在来
的版本中,官⽅会进⼀步调整装饰器的相关语法!

⼆、类装饰器

1. 基本语法

类装饰器是⼀个应⽤在类声明上的函数,可以为类添加额外的功能,或添加额外的逻辑

/*
Demo函数会在Person类定义时执⾏
参数说明:
○ target参数是被装饰的类,即:Person
*/
function Demo(target: Function) {
console.log(target)
}
// 使⽤装饰器
@Demo
class Person { }

2. 应⽤举例

需求:定义⼀个装饰器,实现 Person 实例调⽤ toString 时返回 JSON.stringify 的执⾏结果。

// 使⽤装饰器重写toString⽅法 + 封闭其原型对象
function CustomString(target: Function) {
// 向被装饰类的原型上添加⾃定义的 toString ⽅法
target.prototype.toString = function () {
return JSON.stringify(this)
}
// 封闭其原型对象,禁⽌随意操作其原型对象
Object.seal(target.prototype)
}
// 使⽤ CustomString 装饰器
@CustomString
class Person {
constructor(public name: string, public age: number) { }
speak() {
console.log('你好呀!')
}
}
/* 测试代码如下 */
let p1 = new Person('张三', 18)
// 输出:{"name":"张三","age":18}
console.log(p1.toString())
// 禁⽌随意操作其原型对象
interface Person {
a: any
}
// Person.prototype.a = 100 // 此⾏会报错:Cannot add property a, object is not
extensible
// console.log(p1.a)

3. 关于返回值

类装饰器有返回值:若类装饰器返回⼀个新的类,那这个新类将替换掉被装饰的类。
类装饰器⽆返回值:若类装饰器⽆返回值或返回 undefined,那被装饰的类不会被替换。

function demo(target:Function){
// 装饰器有返回值时,该返回值会替换掉被装饰的类
return class {
test(){
console.log(200)
console.log(300)
console.log(400)
}
}
}
@demo
class Person {
test(){
console.log(100)
}
}
console.log(Person)

4. 关于构造类型

在 TypeScript 中,Function类型所表示的范围⼗分⼴泛,包括:普通函数、箭头函数、⽅法等等。但并⾮Function类型的函数都可以被new关键字实例化,例如箭头函数是不能被实例化的,那么 TypeScript 中概如何声明⼀个构造类型呢?有以下两种⽅式:

仅声明构造类型

/*
○ new 表示:该类型是可以⽤new操作符调⽤。
○ ...args 表示:构造器可以接受【任意数量】的参数。
○ any[] 表示:构造器可以接受【任意类型】的参数。
○ {} 表示:返回类型是对象(⾮null、⾮undefined的对象)。
*/
// 定义Constructor类型,其含义是构造类型
type Constructor = new (...args: any[]) => {};
function test(fn:Constructor){}
class Person {}
test(Person)

声明构造类型 + 指定静态属性

// 定义⼀个构造类型,且包含⼀个静态属性 wife
type Constructor = {
new(...args: any[]): {}; // 构造签名
wife: string; // wife属性
};
function test(fn:Constructor){}
class Person {
static wife = 'asd'
}
test(Person)

5. 替换被装饰的类

对于⾼级⼀些的装饰器,不仅仅是覆盖⼀个原型上的⽅法,还要有更多功能,例如添加新的⽅法和 状态。

需求:设计⼀个 LogTime 装饰器,可以给实例添加⼀个属性,⽤于记录实例对象的创建时间,再添加⼀个⽅法⽤于读取创建时间。

// User接⼝
interface User {
getTime(): Date
log(): void
}
// ⾃定义类型Class
type Constructor = new (...args: any[]) => {}
// 创建⼀个装饰器,为类添加⽇志功能和创建时间
function LogTime<T extends Constructor>(target: T) {
return class extends target {
createdTime: Date;
constructor(...args: any[]) {
super(...args);
this.createdTime = new Date(); // 记录对象创建时间
}
getTime() {
return `该对象创建时间为:${this.createdTime}`;
}
};
}
@LogTime
class User {
constructor(
public name: string,
public age: number
) { }
speak() {
console.log(`${this.name}说:你好啊!`)
}
}
const user1 = new User('张三', 13);
user1.speak()
console.log(user1.getTime())

三、装饰器⼯⼚

装饰器⼯⼚是⼀个返回装饰器函数的函数,可以为装饰器添加参数,可以更灵活地控制装饰器的⾏为。

需求:定义⼀个 LogInfo 类装饰器⼯⼚,实现 Person 实例可以调⽤到 introduce ⽅法,且 introduce 中输出内容的次数,由 LogInfo 接收的参数决定。

interface Person {
introduce: () => void
}
// 定义⼀个装饰器⼯⼚ LogInfo,它接受⼀个参数 n,返回⼀个类装饰器
function LogInfo(n:number) {
// 装饰器函数,target 是被装饰的类
return function(target: Function){
target.prototype.introduce = function () {
for (let i = 0; i < n; i++) {
console.log(`我的名字:${this.name},我的年龄:${this.age}`)
}
}
}
}
@LogInfo(5)
class Person {
constructor(
public name: string,
public age: number
) { }
speak() {
console.log('你好呀!')
}
}
let p1 = new Person('张三', 18)
// console.log(p1) // 打印的p1是:_classThis,转换的JS版本⽐较旧时,会出现,不必纠结
p1.speak()
p1.introduce()

四、装饰器组合

装饰器可以组合使⽤,执⾏顺序为:先【由上到下】的执⾏所有的装饰器⼯⼚,依次获取到装饰器,然后再【由下到上】执⾏所有的装饰器
装饰器组合 —— 执⾏顺序(控制台打印:test2⼯⼚ test3⼯⼚ test4 test3 test2 test1)从上到下 或者说从左到右

//装饰器
function test1(target:Function) {
console.log('test1')
}
//装饰器⼯⼚
function test2() {
console.log('test2⼯⼚')
return function (target:Function) {
console.log('test2')
}
}
//装饰器⼯⼚
function test3() {
console.log('test3⼯⼚')
return function (target:Function) {
console.log('test3')
}
}
//装饰器
function test4(target:Function) {
console.log('test4')
}
@test1
@test2()
@test3()
@test4
class Person { }

装饰器组合 —— 应⽤

// ⾃定义类型Class
type Constructor = new (...args: any[]) => {}
interface Person {
introduce():void
getTime():void
}
// 使⽤装饰器重写toString⽅法 + 封闭其原型对象
function customToString(target: Function) {
// 向被装饰类的原型上添加⾃定义的 toString ⽅法
target.prototype.toString = function () {
return JSON.stringify(this)
}
// 封闭其原型对象,禁⽌随意操作其原型对象
Object.seal(target.prototype)
}
// 创建⼀个装饰器,为类添加⽇志功能和创建时间
function LogTime<T extends Constructor>(target: T) {
return class extends target {
createdTime: Date;
constructor(...args: any[]) {
super(...args);
this.createdTime = new Date(); // 记录对象创建时间
}
getTime() {
return `该对象创建时间为:${this.createdTime}`;
}
};
}
// 定义⼀个装饰器⼯⼚ LogInfo,它接受⼀个参数 n,返回⼀个类装饰器
function LogInfo(n:number) {
// 装饰器函数,target 是被装饰的类
return function(target: Function){
target.prototype.introduce = function () {
for (let i = 0; i < n; i++) {
console.log(`我的名字:${this.name},我的年龄:${this.age}`)
}
}
}
}
@customToString
@LogInfo(3)
@LogTime
class Person {
constructor(
public name: string,
public age: number
) { }
speak() {
console.log('你好呀!')
}
}
const p1 = new Person('张三',18)
console.log(p1.toString())
p1.introduce()
console.log(p1.getTime())

上面说的这么多全都是类的装饰器,接下来是属性装饰器了

五、属性装饰器

  1. 基本语法

标签:function,console,log,TS,Person,聊聊,装饰,target
From: https://blog.csdn.net/ytpedancerow/article/details/143641342

相关文章

  • 解决R报错: fatal error: hb-ft.h: No such file or directory 下载textshaping时
    >下载textshaping包,出现路径依赖错误。#解决路径依赖问题```condainstall-cconda-forgeharfbuzzfreetypefribidipkg-configwhichpkg-config  #看是否返回路径,返回即正常find/-name"harfbuzz.pc"2>/dev/nullfind/-name"freetype2.pc"2>/dev/nullfi......
  • 鸿蒙next5.0版开发:ArkTS组件点击事件详解
    在HarmonyOS5.0中,ArkTS提供了一套完整的组件和事件处理机制,使得开发者能够创建交互性强的应用程序。本文将详细解读如何使用ArkTS组件处理点击事件,包括事件的注册、回调函数的编写以及事件对象的使用。点击事件基础点击事件是用户与应用交互的基本方式之一。在ArkTS中,点击......
  • CSS中 特性查询(@supports)详解及使用
    1.简介CSS中的@supports用于检测浏览器是否支持CSS的某个属性。其实就是条件判断,如果支持某个属性可以写一套样式,如果不支持某个属性,可以提供另外一套样式作为替补。可以放在代码的顶层,也可以嵌套在任何其他条件组规则中。语法@supports规则由一组样式声明和一条支持条件构......
  • Google Fonts API 使用入门
    本指南介绍了如何使用GoogleFontsAPI向网页添加字体。您无需进行任何编程;您只需向HTML文档添加一个特殊的样式表链接,然后以CSS样式引用该字体即可。https://www.octfgroup.com/简单示例下面是一个示例。将以下HTML复制并粘贴到文件中:<html><head><metacharset="utf-8......
  • CF1625E2. Cats on the Upgrade
    题目题解题目给了很重要的性质,就是保证询问的[l,r]是合法括号串(没有的话可能要莫队+二分找?)假设给出的s串是合法括号序,按照树转括号序的方法逆向转成树,用左括号下标作为树上点的标号例如()(()()),则有root-1,root-3,3-4,3-6,方法是维护左括号的栈,加入右括号时弹左括号t1,然......
  • LitServe 服务多worker启动简单说明
    LitServe是一个基于fastapi包装的快速推理api服务,以下只简单说明下关于server启动部分的处理参考使用我们可以通过配置devices以及每个device对应的worker数执行以那种模式进行server的启动(多线程还是多进程)参考使用if__name__=="__main__":#EnabletheOp......
  • 鸿蒙开发进阶(HarmonyOS)录像实现方案(ArkTS)
     鸿蒙NEXT开发实战往期必看文章:一分钟了解”纯血版!鸿蒙HarmonyOSNext应用开发!“非常详细的”鸿蒙HarmonyOSNext应用开发学习路线!(从零基础入门到精通)HarmonyOSNEXT应用开发案例实践总结合(持续更新......)HarmonyOSNEXT应用开发性能优化实践总结(持续更新......)当前示......
  • 【GreatSQL 优化器 - 01】const_table
    一、const_table介绍GreatSQL的优化器主要用JOIN类来进行处理SQL语句的,JOIN类有以下四个table数量相关的成员变量。其中const_tables是optimize最开始就检查并且标识的,因为这样可以把记录最少的表放在执行计划的第一步,在后面的执行计划里面这些consttables是不参......
  • 基于SpringBoot+Vue的装饰工程管理系统设计与实现毕设(文档+源码)
            目录一、项目介绍二、开发环境三、功能介绍四、核心代码五、效果图六、源码获取:         大家好呀,我是一个混迹在java圈的码农。今天要和大家分享的是一款基于SpringBoot+Vue的装饰工程管理系统,项目源码请点击文章末尾联系我哦~目前有各类成......
  • Ubuntu 22.04.1 LTS 安装 MinIO
    1. 创建数据目录#数据存储目录mkdir-p/mnt/c/aipc/minio#日志存储目录cd/mnt/c/aipc/miniomkdir-plogsconfdatachmod-R777/mnt/c/aipc/minio2.安装wgethttps://dl.min.io/server/minio/release/linux-amd64/minio#将下载所得minio文件拷贝到指定文件夹......