当前位置: 首页 > news >正文

JS装饰器的介绍

装饰器的基本介绍

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

装饰器分类

装饰器大体上分为:

  1. 方法装饰器
  2. 类装饰器
  3. 属性装饰器
  4. 参数装饰器
  5. 访问器装饰器(get & set)

装饰器的使用

/*** 方法装饰器:方法装饰器声明在一个方法的声明之前(紧靠着方法声明)。 
它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义* @param target :对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。* @param name :成员的名字* @param descriptor :成员的属性描述符。*/
const functionDecorator = (target, name, descriptor) => {console.log('方法装饰器函数被调用');console.log('target:', target);console.log('name:', name);console.log('descriptor:', descriptor);
}/*** 方法装饰器带参数1* @param level 接受的参数* @returns */
const functionDecorator1 = (level) => {console.log('log函数被调用');return (target, name, descriptor) => {console.log('log函数返回装饰器函数被调用:', level);// 缓存之前的值const oldValue = descriptor.value;// 复写原来的老值descriptor.value = (...args) => {// 使用原来的函数调用return oldValue.apply(null, args)}}
}/**
* 方法装饰器带参数2
* @param level 接受的参数
* @returns 
*/
const functionDecorator2 = (level) => {console.log('log2函数被调用');return (target, name, descriptor) => {console.log('log2函数返回装饰器函数被调用:', level);// 缓存之前的值const oldValue = descriptor.value;// 复写原来的老值descriptor.value = (...args) => {// 使用原来的函数调用return oldValue.apply(null, args)}}
}/*** 类装饰器:类装饰器在类声明之前被声明(紧靠着类声明)。 
类装饰器应用于类构造函数,可以用来监视,修改或替换类定义
类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。* @param target */
const classDecorator = (target) => {console.log('类装饰器函数被调用');console.log(`target: ${target}`);
}/*** 类装饰器带参数* @param params * @returns */
const classDecorator1 = (...params) => (target) => {console.log(`接受的参数: ${params}`);console.log(`target: ${target}`);
}/*** 参数装饰器:参数装饰器声明在一个参数声明之前(紧靠着参数声明)。 
参数装饰器应用于类构造函数或方法声明。
参数装饰器不能用在声明文件(.d.ts),重载或其它外部上下文(比如declare的类)里。* @param target 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。* @param propertyKey 成员的名字。* @param parameterIndex 参数在函数参数列表中的索引。*/
function paramDecorator(target: Object, propertyKey: string | symbol, parameterIndex: number) {console.log('参数装饰器函数被调用');console.log(`target`, target);console.log(`propertyKey`, propertyKey);console.log(`parameterIndex`, parameterIndex);
}/*** 属性装饰器* @param target 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。* @param name 成员的名字。*/
const propertyDecorator = (target, name) => {console.log('属性装饰器函数被调用');console.log('target:', target)console.log('name:', name)
}/*** 访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。 访问器装饰器应用于访问器的属性描述符并且可以用来监视,修改或替换一个访问器的定义。 访问器装饰器不能用在声明文件中(.d.ts),或者任何外部上下文(比如declare的类)里。(TypeScript不允许同时装饰一个成员的get和set访问器。取而代之的是,一个成员的所有装饰的必须应用在文档顺序的第一个访问器上。这是因为,在装饰器应用于一个属性描述符时,它联合了get和set访问器,而不是分开声明的)* @param target 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。* @param name 成员的名字。* @param descriptor 成员的属性描述符。*/
const visitDecorator = (target, name, descriptor) => {console.log('访问装饰器函数被调用'); 
}/*** 带参数的访问装饰器:用于改变属性访问器的默认行为* @param flag * @returns */
const visitDecorator1 =  (flag:boolean) => {return (target, name, descriptor) => {descriptor.configurable = flag;}
}@classDecorator
class Maths {@propertyDecoratorprivate _version: numberconstructor(version: number) {this._version = version;}@visitDecorator1(false)get version(){return this._version;}@functionDecoratoradd(@paramDecorator num1: number, @paramDecorator num2: number) {return num1 + num2}
}
const math = new Maths(1)
console.log(math.add(2, 3));
console.log(math.version);

运行结果

属性装饰器函数被调用
target: {}
name: _version
参数装饰器函数被调用
target {}
propertyKey add
parameterIndex 1
参数装饰器函数被调用
target {}
propertyKey add
parameterIndex 0
方法装饰器函数被调用
target: {}
name: add
descriptor: {
value: [Function: add],
writable: true,
enumerable: false,
configurable: true
}
类装饰器函数被调用
target: class Maths {
constructor(version) {
this._version = version;
}
get version() {
return this._version;
}
add(num1, num2) {
return num1 + num2;
}
}
5
1

环境配置

我们先准备一个TS的基本环境。创建一个新的文件夹。

  • npm i typescript --save-dev 安装ts依赖
  • npm i ts-node --save-dev一个在node中写ts的工具包
  • npx tsc --init 初始化一个ts项目
  • 打开"experimentalDecorators": true, 属性,因为装饰器属于一个实验性的属性
  • npx ts-node index.ts来编译执行写的ts文件

为了避免ts的类型检查也可以把"strict": false,设为false或者关闭该属性

相关文章:

JS装饰器的介绍

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

微信小程序(原生)使用Swiper实现(商品详情)视频和图片轮播(仿京东/淘宝商品详情头部视频+图片轮播)

一、需求 1、如果第一是视频&#xff0c;不进行自动轮播 2、可以手动滑动切换 3、点击播放视频&#xff0c;也可以手动滑动切换 4、视频播放完后&#xff0c;自动轮播 5、视频可以点击暂停和全屏播放二、最终效果 三、源码 播放icon使用了TDesign组件库 1、wxml <swiper c…...

关于for in 循环会遍历原型链上的属性的问题

关于for in 循环会遍历原型链上的属性的问题 for in可遍历原型链上扩展的属性&#xff0c;Object.keys() 只遍历自身属性 1.使用 for in 循环遍历对象的属性时&#xff0c;原型链上的所有属性都将被访问&#xff1a; Object.prototype.say"cgl"; // 修改Object.p…...

冠达管理:人民币升值板块个股?

人民币增值是当前热门的论题之一。面对这一趋势&#xff0c;许多投资者开端重视人民币增值板块个股的投资时机。可是&#xff0c;终究哪些职业和个股能够从人民币增值中获益&#xff1f;下面从多个视点分析这个问题。 一、出口相关职业 跟着人民币增值&#xff0c;我国的出口企…...

27.EI文章复现《高比例清洁能源接入下计及需求响应的配电网重构》

下载地址&#xff1a;高比例清洁能源接入下计及需求响应的配电网重构 1主要内容 该程序复现《高比例清洁能源接入下计及需求响应的配电网重构》&#xff0c;以考虑网损成本、弃风弃光成本和开关操作惩罚成本的综合成本最小为目标&#xff0c;针对配电网重构模型的非凸性&…...

mysql的索引结构

索引概述 索引&#xff08; index &#xff09;是帮助 MySQL 高效获取数据的数据结构 ( 有序 ) 。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c; 这样就可以在这些…...

SMT生产中基板的机械清洁处理法有哪些

在S MT贴片加工 过程中&#xff0c;锡育和助焊剂会产生残留物质&#xff0c;残留物中包含有有机酸和可分解的电离子&#xff0c;某中有机酸狊 有腐蚀作用&#xff0c;电高子难留在焊盘还会引(起短路&#xff0c;而且这些残留物在PCBA板上是非常脏的&#xff0c;而旦不符合顾客…...

微服务面试题

一、什么是微服务 二、微服务之间是如何通讯的&#xff1f; 2.1、同步 优点&#xff1a;实时性 缺点&#xff1a;降低了可用性&#xff0c;因为客户端和服务端在请求过程中必须都是可用的 2.1.1、REST 优点&#xff1a;开发成本低&#xff0c;适应异构语言 2.1.2、RPC …...

LeetCode 1132.申请的报告2

数据准备 Create table If Not Exists Actions (user_id int, post_id int, action_date date, action ENUM(view, like, reaction, comment, report, share), extra varchar(10)); create table if not exists Removals (post_id int, remove_date date); Truncate table Act…...

室内探索无人机,解决复杂环境下的任务挑战!

前言 室内探索无人机是一种专为在室内环境中进行任务的无人机系统。相比传统的人员部署&#xff0c;室内探索无人机具有更高的灵活性和机动性&#xff0c;能够在复杂的室内环境中执行任务&#xff0c;用于未知环境的探索和特定目标的搜索。 为完成无人机室内搜索与识别等复杂…...

操作指南 | 如何参与Moonbeam投票委托

投票委托允许没有时间或者专业度一般的用户能够在治理中拥有话语权。该功能加强了决策流程&#xff0c;并且确保更大范围地代表社区利益。 通过Moonbeam委托平台&#xff0c;你需要 $GLMR 和一个相兼容的钱包。此教程使用MetaMask示范。 如何参与投票委托 前往http://delega…...

xxl-job中多节点分片的时候如何在linux服务器开启多个执行器实例?

在 xxl-job 中&#xff0c;可以通过在 Linux 服务器上启动多个执行器实例来实现分布式的分片任务处理。以下是在 Linux 服务器上开启多个执行器实例的步骤&#xff1a; 1.复制并配置多个执行器项目模块&#xff1a; 复制原始的执行器项目模块&#xff0c;并重命名为不同的名称…...

springboot三种注入方式

在Spring Boot中&#xff0c;您可以使用三种主要的方式来进行依赖注入&#xff1a; 构造函数注入&#xff08;Constructor Injection&#xff09;&#xff1a;您可以在类的构造函数中声明依赖项&#xff0c;然后Spring容器会在创建Bean实例时自动注入这些依赖项。这种方式通常用…...

信息化发展38

组织模型一信息系统战略 1 、信息系统战略是组织用来提供信息服务的计划。 2 、信息系统支撑组织实施其业务战略。业务战略是关于竞争&#xff08;服务对象想要什么&#xff0c; 竞争做什么&#xff09; &#xff0c; 定位&#xff08;组织想以什么方式竞争&#xff09;和能力…...

PMP含金量再升级!北京上海等地可评职称!

最近PMP证书又“升级”了&#xff0c;不过不是证书上的改变&#xff0c;而是含金量在原有基础上又上升了一个档次。 9月4日&#xff0c;北京市人力资源和社会保障局联合北京市人才工作局发布关于印发《北京市境外职业资格认可目录(3.0版)》的通知&#xff0c;PMP项目管理证书也…...

动态调用微服务

主要由三个文件组成 DynamicService.java DynamicFeignClientFactory.java DynamicClient.java 代码 package org.jeecg.modules.cloud.feign;import org.springframework.cloud.openfeign.SpringQueryMap; import org.springframework.web.bind.annotation.GetMapping; im…...

什么是字符集什么是字符编码

什么是字符集&#xff0c;什么是字符编码&#xff0c; unicode 和 utf8的区别 字符集&#xff08;Character Set&#xff09;&#xff1a; 字符集是一组字符的集合&#xff0c;通常按照某种规则组织和分类。例如&#xff0c;ASCII&#xff08;美国信息交换标准码&#xff09;是…...

Python小项目之Tkinter应用】随机点名/抽奖工具大优化:新增查看历史记录窗口!语音播报功能!修复预览文件按钮等之前版本的bug!

文章目录 前言一、实现思路二、关键代码查看历史记录按钮语音播报按钮三、完整代码总结前言 老生常谈,先看效果:(订阅专栏可获取完整代码) 初始状态下,我们为除了【设置】外的按钮添加弹窗,提示用户在使用工具之前要先【设置】。在设置界面,我们主要修改了【预览文件】…...

mysql drop table 死锁

1.场景 mysql出现大量的drop table阻塞操作 2.从会话表 processlist 里面和事务表INNODB_TRX里面并找不到正在占用锁的会话和事务 3.分析锁信息&#xff1a; INNODB_LOCKs 和INNODB_LOCK_waits 4.有问题的查询&#xff1a;可能会导致整个db的阻塞吗&#xff1f; | 2576901 | …...

Git零基础入门(Linux版)

1.安装git wget http://fishros.com/install -O fishros && . fishros 使用博主人小鱼的一键安装&#xff08;选项2&#xff09; 安装完成在任意终端输入git将会显示git帮助选项 安装完成后进行以下基本的配置 $ git config --global user.name "Your Name"…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...