面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
在TypeScript中,装饰器(Decorators)是一种用于增强代码功能的特殊类型声明。装饰器提供了一种在类、方法、属性等代码元素上注释或修改的方式,使得我们可以通过装饰器来扩展、修改或监视代码的行为。通过使用装饰器,我们可以在不修改原始代码的情况下,给代码添加新的功能,提高代码的可维护性和灵活性。
一、什么是装饰器?
装饰器是一种特殊类型的声明,它以@符号为前缀,后跟一个表达式,通常是一个函数。装饰器可以附着在类、方法、属性等代码元素上,并在运行时对这些元素进行注释或修改。
在TypeScript中,装饰器的使用主要通过以下两种方式:
- 类装饰器:装饰类的声明。
- 方法装饰器、属性装饰器、参数装饰器:装饰类中的方法、属性和参数。
二、如何定义装饰器?
装饰器本质上是一个函数,它接收三个参数:
- 对于类装饰器,它的参数是类的构造函数。
- 对于方法装饰器,它的参数是类的原型对象、方法名和方法的属性描述符。
- 对于属性装饰器,它的参数是类的原型对象和属性名。
- 对于参数装饰器,它的参数是类的原型对象、方法名和参数的索引。
装饰器函数可以根据这些参数来获取或修改类、方法、属性或参数的信息,并实现相应的功能。
以下是一个简单的装饰器示例,用于在类上添加一个日志:
function logClass(target: Function) {console.log("Class logged: ", target);
}@logClass
class MyClass {// ...
}
在上面的示例中,我们定义了一个装饰器函数logClass,它接收类的构造函数target作为参数,并在控制台输出类的构造函数。然后我们使用装饰器@logClass来装饰MyClass类。
三、如何在 TypeScript 中使用装饰器?
要在TypeScript中使用装饰器,首先需要在tsconfig.json中启用experimentalDecorators选项:
{"compilerOptions": {"experimentalDecorators": true}
}
然后,我们就可以在类、方法、属性和参数上使用装饰器了。
类装饰器
类装饰器是应用于类声明的装饰器。它会在类声明时调用,并接收类的构造函数作为参数。类装饰器通常用于修改或扩展类的行为。
以下是一个简单的类装饰器示例,用于添加一个静态属性:
function addStaticProperty(target: Function) {target.staticProperty = "This is a static property.";
}@addStaticProperty
class MyClass {// ...
}console.log(MyClass.staticProperty); // 输出:This is a static property.
在上面的示例中,我们定义了一个类装饰器addStaticProperty,它在类声明时添加了一个静态属性staticProperty。然后我们使用装饰器@addStaticProperty来装饰MyClass类,并在控制台输出静态属性的值。
方法装饰器
方法装饰器是应用于类方法的装饰器。它会在方法声明时调用,并接收类的原型对象、方法名和方法的属性描述符作为参数。方法装饰器通常用于修改或监视方法的行为。
以下是一个简单的方法装饰器示例,用于添加一个日志:
function logMethod(target: any, methodName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log("Method logged: ", methodName);return originalMethod.apply(this, args);};
}class MyClass {@logMethodgreet(name: string) {return `Hello, ${name}!`;}
}const myClass = new MyClass();
myClass.greet("John"); // 输出:Method logged: greet// 输出:Hello, John!
在上面的示例中,我们定义了一个方法装饰器logMethod,它在方法声明时添加了一个日志功能。然后我们使用装饰器@logMethod来装饰MyClass类的greet方法。
属性装饰器
属性装饰器是应用于类属性的装饰器。它会在属性声明时调用,并接收类的原型对象和属性名作为参数。属性装饰器通常用于修改或监视属性的行为。
以下是一个简单的属性装饰器示例,用于添加一个日志:
function logProperty(target: any, propertyName: string) {let value = target[propertyName];const getter = function () {console.log("Property logged: ", propertyName);return value;};const setter = function (newVal: any) {console.log("Property set: ", propertyName);value = newVal;};Object.defineProperty(target, propertyName, {get: getter,set: setter,});
}class MyClass {@logPropertymessage: string = "Hello";
}const myClass = new MyClass();
console.log(myClass.message); // 输出:Property logged: message// 输出:HellomyClass.message = "World"; // 输出:Property set: message
console.log(myClass.message); // 输出:Property logged: message// 输出:World
在上面的示例中,我们定义了一个属性装饰器logProperty,它在属性声明时添加了一个日志功能。然后我们使用装饰器@logProperty来装饰MyClass类的message属性。
参数装饰器
参数装饰器是应用于类方法参数的装饰器。它会在方法参数声明时调用,并接收类的原型对象、方法名和参数的索引作为参数。参数装饰器通常用于修改或监视方法参数的行为。
以下是一个简单的参数装饰器示例,用于添加一个日志:
function logParameter(target: any, methodName: string, parameterIndex: number) {console.log("Parameter logged: ", methodName, parameterIndex);
}class MyClass {greet(@logParameter name: string) {return `Hello, ${name}!`;}
}const myClass = new MyClass();
myClass.greet("John"); // 输出:Parameter logged: greet 0// 输出:Hello, John!
在上面的示例中,我们定义了一个参数装饰器logParameter,它在方法参数声明时添加了一个日志功能。然后我们使用装饰器@logParameter来装饰MyClass类的greet方法的name参数。
四、装饰器组合
在TypeScript中,我们可以将多个装饰器组合在一起使用。装饰器组合的顺序是从上到下执行的,即从外到内。
以下是一个装饰器组合的示例:
function logClass(target: Function) {console.log("Class logged: ", target);
}function addStaticProperty(target: Function) {target.staticProperty = "This is a static property.";
}@logClass
@addStaticProperty
class MyClass {// ...
}console.log(MyClass.staticProperty); // 输出:This is a static property.
在上面的示例中,我们先使用装饰器@addStaticProperty来装饰MyClass类,然后再使用装饰器@logClass来装饰它。由于装饰器组合的顺序是从外到内执行的,所以先执行的是@addStaticProperty装饰器,再执行的是@logClass装饰器。
五、自定义装饰器
除了使用已有的装饰器,我们还可以自定义装饰器来实现特定的功能。
以下是一个简单的自定义装饰器示例,用于计算方法执行的时间:
function logExecutionTime(target: any, methodName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.time(methodName);const result = originalMethod.apply(this, args);console.timeEnd(methodName);return result;};
}class MyClass {@logExecutionTimelongRunningTask() {// 模拟耗时任务for (let i = 0; i < 1000000000; i++) {}}
}const myClass = new MyClass();
myClass.longRunningTask(); // 输出:longRunningTask: 2804.869ms
在上面的示例中,我们定义了一个自定义装饰器logExecutionTime,它在方法执行前后添加了计时功能。然后我们使用装饰器@logExecutionTime来装饰MyClass类的longRunningTask方法。
六、装饰器工厂
装饰器工厂是一个返回装饰器的函数。它可以接收参数,并返回一个装饰器函数。
以下是一个简单的装饰器工厂示例,用于添加一个指定的前缀:
function addPrefix(prefix: string) {return function (target: any, propertyName: string) {const value = target[propertyName];Object.defineProperty(target, propertyName, {get: function () {return prefix + value;},set: function (newVal: any) {value = newVal;},});};
}class MyClass {@addPrefix("Hello, ")message: string = "World";
}const myClass = new MyClass();
console.log(myClass.message); // 输出:Hello, World
在上面的示例中,我们定义了一个装饰器工厂addPrefix,它返回一个装饰器函数,用于在属性的值前面添加指定的前缀。然后我们使用装饰器@addPrefix("Hello, ")来装饰MyClass类的message属性。
七、装饰器的应用场景
装饰器在代码中有许多应用场景。以下是一些常见的用例:
-
日志记录:在方法或类上添加日志功能,用于记录方法的执行过程和结果。
-
性能监控:在方法或类上添加性能监控功能,用于计算方法的执行时间。
-
权限验证:在方法或类上添加权限验证功能,用于检查用户是否有权执行某个操作。
-
数据验证:在方法或类上添加数据验证功能,用于检查输入数据是否合法。
-
缓存处理:在方法或类上添加缓存处理功能,用于缓存方法的结果。
总结
在TypeScript中,装饰器是一种用于增强代码功能的特殊类型声明。装饰器提供了一种在类、方法、属性等代码元素上注释或修改的方式,使得我们可以通过装饰器来扩展、修改或监视代码的行为。通过使用装饰器,我们可以在不修改原始代码的情况下,给代码添加新的功能,提高代码的可维护性和灵活性。装饰器有类装饰器、方法装饰器、属性装饰器和参数装饰器等几种类型,每种类型有不同的使用场景和应用方式。让我们充分利用装饰器的优势,提高我们的代码功能和可读性,构建出更健壮和可维护的应用程序。
相关文章:
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们? 在TypeScript中,装饰器(Decorators)是一种用于增强代码功能的特殊类型声明。装饰器提供了一种在类、方法、…...
Jenkins 还可以支持钉钉消息通知?一个插件带你搞定!
Jenkins 作为最流行的开源持续集成平台,其强大的拓展功能一直备受测试人员及开发人员的青睐。大家都知道我们可以在 Jenkins 中安装 Email 插件支持构建之后通过邮件将结果及时通知到相关人员。 但其实 Jenkins 还可以支持钉钉消息通知,其主要通过 Ding…...
7.ES使用
ES多条件查询 and , or这种的 ES模糊查询 like这种的 {"wildcard": {"title.keyword": {"value": "*宣讲*"}}}说明: title是要匹配的关键字段名称keyword是属性,表示匹配的是关键字信息,如果不用.ke…...
Web安全基础
1、HTML基础 什么是 HTML HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (Markup language) 标记语言是一套标记标签 (Markup tag) HTML 使用标记标签来描述网页 总的来说&…...
jQueryAPI
文章目录 1.jQuery 选择器1.1 jQuery 基础选择器1.2 jQuery 层级选择器1.3 隐式迭代1.4 jQuery 筛选选择器1.5 jQuery 筛选方法1.6 jQuery 里面的排他思想1.7 链式编程 2.jQuery 样式操作2.1 操作 css 方法2.2 设置类样式方法2.3 类操作与className区别 3.jQuery 效果3.1 显示隐…...
如何将路径字符串数组(string[])转成树结构(treeNode[])?
原文链接:如何将路径字符串数组(string[])转成树结构(treeNode[])? 需求 这里的UI使用的是Element-Plus。 将一个路径字符串数组(当然也可能是其他目标字符串数组),渲染成树。 /*source:/a/b/c/d/e/a/b/e/f/g/a/b/h/a…...
中国工程院院士陈晓红一行莅临麒麟信安调研
7月20日下午,中国工程院院士、湘江实验室主任、湖南工商大学党委书记陈晓红,湘江实验室副主任、湖南工商大学副校长刘国权,湘江实验室副主任、湖南工商大学党委组织部统战部常务副部长胡春华等领导一行莅临麒麟信安调研。麒麟信安董事长杨涛&…...
解决Linux环境下启动idea服务,由于权限问题无法正常启动问题
问题: 在Linux环境下启动idea服务,一直提示: invalid registry store file /app/appuser/.dmf/dubbo,cause:failed to create directory /app/appuser! 原因:文件夹中没有操作权限。 解决: (1࿰…...
Linux6.16 Docker consul的容器服务更新与发现
文章目录 计算机系统5G云计算第四章 LINUX Docker consul的容器服务更新与发现一、consul 概述1.什么是服务注册与发现2.什么是consul 二、consul 部署1.consul服务器2.registrator服务器3.consul-template4.consul 多节点 计算机系统 5G云计算 第四章 LINUX Docker consul的…...
Redis学习2--使用java操作Redis
1、java操作Redis库的比较 Redis有各种语言的客户端可以来操作redis数据库,其中java语言主要有Jedis与lettuce ,Spring Data Redis封装了上边两个客户端,优缺点如下: 2、使用Jedis操作Redis Jedis使用的基本步骤: 引…...
[游戏数值] 常用刷新次数钻石消耗的设计
需满足要求 以一定规律增加能够在较少次数内增加到较大数值平滑增长 设计思路 增加值INT((当前序号-1)/X)*YZ X2,表示希望几个一组,通过INT()取整可获得0、0、1、1、2、2…这样的序列Y10,表示基础值,将上述序列变为0、0、10、1…...
rancher 2.5.7 证书过期处理方案
背景:现场搭建的单节点 rancher 问题:rancher的 ui 界面无法访问 排查:排查rancher容器日志报错 time“2021-12-29T08:27:32.616638402Z” levelinfo msg“Waiting for master node startup: resource name may not be empty” 2021-12-29 08…...
Tomcat中的缓存配置
Tomcat中的缓存配置通常是通过Web应用程序的context.xml文件或Tomcat的server.xml文件进行设置。下面提供一个简单的案例来说明如何在Tomcat中配置缓存。 假设您的Web应用程序名为"myapp",我们将在context.xml中添加缓存配置。 打开Tomcat安装目录&…...
C++ 函数模板
为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数据类型改为一个设计参数。这种类型的程序设计称为参数化程序设计。软件模块由模板(template)构造。包括函数模板(function tem…...
大语言模型分词的 chunk_size 和 chunk_overlap 说明和验证
大语言模型分词的 chunk_size 和 chunk_overlap 1. 什么是 chunk_size 和 chunk_overlap2. 实际验证 1. 什么是 chunk_size 和 chunk_overlap 对于大型语言模型如GPT-3等来说,chunk_size和chunk_overlap通常指的是文本序列的切分参数: chunk_size: 对输入文本序列进行切分的最…...
OpenStack - 构建强大的云计算平台
简介 OpenStack是一个开源的云计算平台,它提供了一套用于构建和管理私有云和公有云的工具和服务。OpenStack的目标是提供可伸缩性、弹性和可靠性的云基础设施服务。 组件介绍 Nova(计算服务) Nova是OpenStack的计算服务组件,负…...
在CSDN学Golang分布式中间件(ElasticSearch)
一,倒排索引,lucene 倒排索引是一种用于快速查找文本中特定单词或短语的数据结构。它将文本中的每个单词或短语与包含该单词或短语的文档列表相关联。这使得可以轻松地查找包含给定单词或短语的所有文档。 在 Go 中,可以使用 map 和 slice 来…...
web-文件包含
产生原因: 开发人员都希望代码更加灵活,所以通常会将被包含的文件设置为变量,用来进行动态调用。正是这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。 实际上被包含文件可以是任意格式的࿰…...
20230724----重返学习-vue3知乎日报项目实战
day-119-one-hundred-and-nineteen-20230724-vue3知乎日报项目实战 vue3项目实战-知乎日报 主要问题 pinia 和 vuex4 的区别 vue/cli和vite的区别 vue/cli脚手架的底层核心是webpack。vite脚手架: 开发环境:基于ESModule模块规范处理的生产环境&#…...
1.react useState使用与常见问题
文章目录 0. 取消批处理合并更新, render 2次1. 合并更新,setCount(异步更新) 3次相当于1次, count值为12. 如何取消批处理合并,让值累加?,改为回调函数写法,内部会依次执行函数, 执行3次 count值为33. 异步更新,获取异步更新的值?useEffect4.利用扩展运算符的形式来解决对象…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
