TypeScript进阶(二)深入理解装饰器

✨ 专栏介绍

TypeScript是一种由微软开发的开源编程语言,它是JavaScript的超集,意味着任何有效的JavaScript代码都是有效的TypeScript代码。TypeScript通过添加静态类型和其他特性来增强JavaScript,使其更适合大型项目和团队开发。

在TypeScript专栏中,我们将深入探讨TypeScript的各个方面,包括语法、类型系统、模块化、面向对象编程等。我们将介绍如何使用TypeScript来构建可维护、可扩展和高效的应用程序。

TypeScript是一种开源的编程语言,它是JavaScript的超集,意味着所有的JavaScript代码都可以在TypeScript中运行。TypeScript添加了静态类型检查和其他一些新特性,以提高代码的可读性、可维护性和可扩展性。
在这里插入图片描述

文章目录

    • ✨ 专栏介绍
    • 引言
    • 基本概念
    • 装饰器的分类
        • 1. 类装饰器
        • 2. 方法装饰器
        • 3. 属性装饰器
        • 4. 参数装饰器
    • 装饰器工厂
    • 装饰器的执行顺序
    • 装饰器的应用场景
        • 日志记录
        • 权限控制
        • 表单验证
        • 性能分析
    • 总结
    • 😶 写在结尾


引言

TypeScript 是一种由微软开发的开源编程语言,它是 JavaScript 的超集,为 JavaScript 添加了静态类型检查和其他一些特性。装饰器是 TypeScript 中一个非常强大的特性,它可以用来修改类、方法、属性等的行为。本文将深入探讨 TypeScript 装饰器的原理和用法。

基本概念

装饰器是一种特殊类型的声明,它可以被附加到类声明、方法、属性或参数上,以修改类的行为。装饰器使用 @ 符号作为前缀,并放置在被修饰项之前。

装饰器的分类

在 TypeScript 中,装饰器可以分为四种类型:类装饰器、方法装饰器、属性装饰器和参数装饰器。

1. 类装饰器

类装饰器是应用于类构造函数的函数。它接收一个参数,即被修饰的类构造函数,并可以在不修改原始类定义的情况下扩展或修改该类。

function logClass(target: any) {console.log(target);
}@logClass
class MyClass {// ...
}
2. 方法装饰器

方法装饰器是应用于方法定义的函数。它接收三个参数:被修饰的类的原型、方法的名称和方法的属性描述符。方法装饰器可以用来修改方法的行为,例如添加日志、验证等。

function logMethod(target: any, methodName: string, descriptor: PropertyDescriptor) {console.log(target, methodName, descriptor);
}class MyClass {@logMethodmyMethod() {// ...}
}
3. 属性装饰器

属性装饰器是应用于属性声明的函数。它接收两个参数:被修饰的类的原型和属性名称。属性装饰器可以用来修改属性的行为,例如添加验证、计算等。

function logProperty(target: any, propertyName: string) {console.log(target, propertyName);
}class MyClass {@logPropertymyProperty: string;
}
4. 参数装饰器

参数装饰器是应用于函数参数声明的函数。它接收三个参数:被修饰的类的原型、方法名称和参数索引。参数装饰器可以用来修改函数参数的行为,例如添加验证、转换等。

function logParameter(target: any, methodName: string, parameterIndex: number) {console.log(target, methodName, parameterIndex);
}class MyClass {myMethod(@logParameter param1: string) {// ...}
}

装饰器工厂

除了直接使用装饰器函数,我们还可以使用装饰器工厂来创建装饰器。装饰器工厂是一个返回装饰器函数的函数,它可以接收参数,并根据参数返回不同的装饰器。

function logClassFactory(prefix: string) {return function (target: any) {console.log(`${prefix} ${target}`);};
}@logClassFactory('Logging')
class MyClass {// ...
}

装饰器的执行顺序

当一个类有多个装饰器时,它们的执行顺序是从下到上、从右到左的。这意味着最后一个装饰器先执行,然后依次向上执行。

function log1(target: any) {console.log('log1');
}function log2(target: any) {console.log('log2');
}@log1
@log2
class MyClass {// ...
}

输出结果:

log2 log1

装饰器的应用场景

装饰器在 TypeScript 中有广泛的应用场景,例如:

  • 日志记录:可以使用类装饰器或方法装饰器来添加日志记录功能。
  • 权限控制:可以使用方法装饰器来限制只有特定角色或权限才能调用某个方法。
  • 表单验证:可以使用属性装饰器或参数装饰器来验证表单字段的合法性。
  • 性能分析:可以使用方法装饰器来记录方法的执行时间,以便进行性能分析。
日志记录

当涉及到日志记录时,可以使用类装饰器或方法装饰器来添加日志记录功能。例如,我们可以创建一个类装饰器 @logClass,在类的构造函数中添加日志记录的逻辑。这样,在每次创建该类的实例时,都会自动记录相关日志信息。

function logClass(target: any) {const originalConstructor = target;const newConstructor: any = function (...args: any[]) {console.log(`Creating instance of ${originalConstructor.name}`);return new originalConstructor(...args);};newConstructor.prototype = originalConstructor.prototype;return newConstructor;
}@logClass
class MyClass {constructor() {console.log('MyClass constructor');}
}const myInstance = new MyClass();
权限控制

在权限控制方面,可以使用方法装饰器来限制只有特定角色或权限才能调用某个方法。例如,我们可以创建一个方法装饰器 @checkPermission,在调用被修饰的方法之前进行权限验证。

function checkPermission(target: any, methodName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {// 检查用户权限if (hasPermission()) {return originalMethod.apply(this, args);} else {throw new Error('You do not have permission to access this method.');}};
}class MyClass {@checkPermissionmyMethod() {console.log('Executing myMethod');}
}const myInstance = new MyClass();
myInstance.myMethod(); // 只有具有权限的用户才能成功调用该方法
表单验证

在表单验证方面,可以使用属性装饰器或参数装饰器来验证表单字段的合法性。例如,我们可以创建一个属性装饰器 @validateField,在设置属性值时进行验证。

function validateField(target: any, propertyName: string) {const originalValue = target[propertyName];Object.defineProperty(target, propertyName, {get() {return originalValue;},set(value: any) {// 进行字段验证if (isValid(value)) {originalValue = value;} else {throw new Error(`Invalid value for ${propertyName}`);}},});
}class Form {@validateFieldname: string;constructor(name: string) {this.name = name;}
}const form = new Form('John');
form.name = 'Jane'; // 合法的值
form.name = ''; // 非法的值,会抛出错误
性能分析

在性能分析方面,可以使用方法装饰器来记录方法的执行时间,以便进行性能分析。例如,我们可以创建一个方法装饰器 @measurePerformance,在调用被修饰的方法时记录执行时间。

function measurePerformance(target: any, methodName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {const start = performance.now();const result = originalMethod.apply(this, args);const end = performance.now();console.log(`Method ${methodName} took ${end - start} milliseconds to execute.`);return result;};
}class MyClass {@measurePerformancemyMethod() {// 执行一些耗时的操作for (let i = 0; i < 1000000000; i++) {// ...}}
}const myInstance = new MyClass();
myInstance.myMethod(); // 输出方法执行时间

这些示例展示了装饰器在不同场景下的应用。通过使用装饰器,我们可以轻松地为类、方法、属性或参数添加额外的功能和行为,从而实现更加灵活和可扩展的代码结构。

总结

本文深入探讨了 TypeScript 装饰器的原理和用法。装饰器是 TypeScript 中一个非常强大的特性,它可以用来修改类、方法、属性等的行为。通过使用装饰器,我们可以轻松地扩展和修改现有的类和方法,使其具有更多的功能和特性。


😶 写在结尾

前端设计模式专栏
在这里插入图片描述
设计模式是软件开发中不可或缺的一部分,它们帮助我们解决了许多常见问题,并提供了一种优雅而可靠的方式来构建应用程序。在本专栏中,我们介绍了所有的前端设计模式,包括观察者模式、单例模式、策略模式等等。通过学习这些设计模式,并将其应用于实际项目中,我们可以提高代码的可维护性、可扩展性和可重用性。希望这个专栏能够帮助你在前端开发中更好地应用设计模式,写出高质量的代码。点击订阅前端设计模式专栏

Vue专栏
在这里插入图片描述
Vue.js是一款流行的JavaScript框架,用于构建用户界面。它采用了MVVM(Model-View-ViewModel)的架构模式,通过数据驱动和组件化的方式,使开发者能够更轻松地构建交互性强、可复用的Web应用程序。在这个专栏中,我们将深入探讨Vue.js的核心概念、组件开发、状态管理、路由和性能优化等方面的知识。我们将学习如何使用Vue.js构建响应式的用户界面,并探索其强大的生态系统,如Vue Router和Vuex、Pinia。通过学习这些内容,你将能够成为一名熟练的Vue.js开发者,并能够应用这些知识来构建复杂而高效的Web应用程序。点击订阅Vue专栏

JavaScript(ES6)专栏在这里插入图片描述
JavaScript是一种广泛应用于网页开发和后端开发的脚本语言。它具有动态性、灵活性和易学性的特点,是构建现代Web应用程序的重要工具之一。在这个专栏中,我们将深入探讨JavaScript语言的基本语法、DOM操作、事件处理、异步编程以及常见算法和数据结构等内容。此外,我们还将介绍ES6(ECMAScript 2015)及其后续版本中引入的新特性,如箭头函数、模块化、解构赋值等。通过学习这些内容,你将能够成为一名熟练的JavaScript开发者,并能够应用这些知识来构建出高质量和可维护的Web应用程序。点击订阅JavaScript(ES6)专栏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【解决】Unity Project 面板资源显示丢失的异常问题处理

开发平台&#xff1a;Unity 2021.3.7f1c1   一、问题描述 在开发过程中&#xff0c;遭遇 Project 面板资源显示丢失、不全的问题。但 Unity Console 并未发出错误提示。   二、解决方案&#xff1a;删除 Library 目录 前往 “工程目录/Library” 删除内部所有文件并重打开该…

【JVM】本地方法接口 Native Interface

一、JNI简介 JVM本地方法接口&#xff08;Java Native Interface&#xff0c;JNI&#xff09;是一种允许Java代码调用本地方法&#xff08;如C或C编写的方法&#xff09;的机制。这种技术通常用于实现高性能的计算密集型任务&#xff0c;或者与底层系统库进行交互。 二、JNI组…

Python教程16:使用海龟画图turtle画会动的时钟

---------------turtle源码集合--------------- Python教程36&#xff1a;海龟画图turtle写春联 Python源码35&#xff1a;海龟画图turtle画中国结 Python源码31&#xff1a;海龟画图turtle画七道彩虹 Python源码30&#xff1a;海龟画图turtle画紫色的小熊 Python源码29&a…

CRMEB多商户短信开发

在使用CRMEB多商户系统的时候&#xff0c;想要二开使用其他平台的短信&#xff0c;这里以阿里云短信为例的具体实现方法。 一、加载阿里云短信的SDK&#xff0c;执行命令&#xff1a;composer require alibabacloud/dysmsapi-20170525 二、增加阿里云短信的驱动 1.在 crmeb\…

【REST2SQL】07 GO 操作 Mysql 数据库

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 MySQL是一个关系型数据库管理系统&#xf…

什么是编程思路?如何训练提升自己的编程思路?

哈喽&#xff0c;大家上午好呀&#xff01;又和大家如期见面了&#xff01; 今天给大家分享改变编程思路的9条技巧。 1.拆分项目&#xff0c;再编程 先按大类写子程序&#xff0c;例如自动&#xff0c;手动&#xff0c;报警&#xff0c;然后子程序中写FB块&#xff0c;FC程序&…

el-upload实现可替换、删除、预览的图片上传。js 往返缓存(可判断当前页面是不是返回的页面)

el-upload实现可替换、删除、预览的图片上传 组件使用&#xff1a; <template><div><UploadImage sendUrl :limit"1" :size"size" :gifSize"gifSize" v-model"images"></UploadImage> </div> </tem…

【Linux】Linux系统编程——Linux目录结构

Linux的文件系统呈现为一种树状结构&#xff0c;以根目录/为最顶层&#xff0c;其下分布着各种不同的子目录&#xff0c;每个目录都有其特定的用途和功能。下面是Linux目录结构的详细介绍&#xff1a; 1. 根目录 / 根目录是整个文件系统的基础。所有的目录和文件都从这里开始…

LeetCode刷题13:回溯+剪枝解决216.组合总和 III

找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 解…

阿里云c8i服务器CPU性能、架构及费用测评

阿里云第八代云服务器ECS计算型c8i实例&#xff0c;CPU采用Intel Xeon Emerald Rapids或者Intel Xeon Sapphire Rapids&#xff0c;主频不低于2.7 GHz&#xff0c;全核睿频3.2&#xff0c;阿里云百科aliyunbaike.com分享阿里云c8i服务器CPU处理器型号、存储、网络、安全、使用场…

子域名收集

目录 1、OneForAll 2、利用Google的搜索 3、fofa 4、使用在线查询网站查询 5、利用ip反查 6、Layer子域名挖掘机 7、JSFinder 用法 在进行渗透的过程中有一个很重要的工作就是信息收集&#xff0c;而信息收集中的子域名收集是很重要的一项工作&#xff0c;在本篇中我会给大…

绝地求生:【PC】2024年1月商店更新

亲爱的玩家朋友们&#xff0c;大家好&#xff01; 欢迎大家来到闲游盒2024年首次商店更新&#xff01; 我们在1月商店更新中准备了全新生存通行证&#xff1a;龙腾&#xff0c;彩色烟雾皮肤&#xff0c;地狱天使 VS 天堂恶魔系列皮肤&#xff0c;相信大家一定会喜欢~ 实用腰带…

Linux操作系统——进程控制(三) 进程程序替换

前言 目前我们接触到我们所创建的所有的子进程&#xff0c;它执行的代码都是父进程代码的一部分&#xff01;那么如果我们想让子进程执行新的程序呢&#xff1f;&#xff1f;&#xff1f;执行全新的代码和访问全新的数据&#xff0c;不在和父进程有瓜葛&#xff0c;我们该怎么…

一文详解向量数据库Milvus Cloud动态 Schema

在数据库中&#xff0c;Schema 常有&#xff0c;而动态 Schema 不常有。 例如&#xff0c;SQL 数据库有预定义的 Schema&#xff0c;但这些 Schema 通常都不能修改&#xff0c;用户只有在创建时才能定义 Schema。Schema 的作用是告诉数据库使用者所希望的表结构&#xff0c;确…

如何利用 NFTScan Portfolio 功能分析钱包 NFT 持仓

随着 NFT 市场的扩大和投资者的增加&#xff0c;追踪和管理大量 NFT 资产正变得越来越复杂&#xff0c;无论是新手还是资深投资者&#xff0c;都需要借助实时的 NFT 数据作为判断依据。因此&#xff0c;一个能够全面分析 NFT 钱包持仓的工具就显得尤为重要。帮助投资者掌握自身…

bootstrap搭建一个简单的官网案例附代码

bootstrap搭建一个简单的官网案例附代码 效果常用属性完整代码 效果 大概的效果如下 主要都是用bootstrap的代码实现的 网站是照着 b站视频做的 查看视频教程 建议自己先看一遍文档再跟着视频写&#xff0c;不然可能看不懂 bootstarp中文文档 logo是从别人的站上扒的有点不太协…

阿里巴巴提出AnyText:首个解决多语言视觉文本生成的工作

基于扩散模型的文本到图像在最近取得了令人瞩目的成就。尽管当前的图像合成技术已经非常先进&#xff0c;能够以高保真度生成图像&#xff0c;但当关注生成图像中的文本区域时&#xff0c;往往可能会暴露问题&#xff0c;因为合成文本通常包含模糊、不可读或不正确的字符&#…

firewalld高级配置

IP伪装与端口转发 在互联网发展初期&#xff0c;设计者们并没有想到互联网会发展到现在这个空前繁荣的阶段&#xff0c;所以&#xff0c;设 计的Pv4地址空间只有32位.但是随着互联网的发展&#xff0c;P地址变得严重缺乏&#xff0c;并且地址分配不均匀&#xff0c; 所以就在原…

设计模式-规格模式

设计模式专栏 模式介绍模式特点应用场景规格模式和策略模式的区别和联系代码示例Java实现规格模式Python实现规格模式 规格模式在spring中的应用 模式介绍 规格模式&#xff08;Specification Pattern&#xff09;是一种行为设计模式&#xff0c;其目的是将业务规则封装成可重…

AIGC实战——改进循环神经网络

AIGC实战——改进循环神经网络 0. 前言1. 堆叠循环网络2. 门控制循环单元3. 双向单元相关链接 0. 前言 我们已经学习了如何训练长短期记忆网络 (Long Short-Term Memory Network, LSTM) 模型&#xff0c;以学习使用给定风格生成文本&#xff0c;接下来&#xff0c;我们将学习如…