TypeScript之装饰器

一、是什么

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上

是一种在不改变原类和使用继承的情况下,动态地扩展对象功能

同样的,本质也不是什么高大上的结构,就是一个普通的函数,@expression 的形式其实是Object.defineProperty的语法糖

expression求值后必须也是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入

二、使用方式

由于typescript是一个实验性特性,若要使用,需要在tsconfig.json文件启动,如下:

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

typescript装饰器的使用和javascript基本一致

类的装饰器可以装饰:

  • 方法/属性

  • 参数

  • 访问器

类装饰

例如声明一个函数 addAge 去给 Class 的属性 age 添加年龄.

function addAge(constructor: Function) {
  constructor.prototype.age = 18;
}

@addAge
class Person{
  name: string;
  age!: number;
  constructor() {
    this.name = 'huihui';
  }
}

let person = new Person();

console.log(person.age); // 18

上述代码,实际等同于以下形式:

Person = addAge(function Person() { ... });

上述可以看到,当装饰器作为修饰类的时候,会把构造器传递进去。 constructor.prototype.age 就是在每一个实例化对象上面添加一个 age 属性

方法/属性装饰

同样,装饰器可以用于修饰类的方法,这时候装饰器函数接收的参数变成了:

  • target:对象的原型
  • propertyKey:方法的名称
  • descriptor:方法的属性描述符

可以看到,这三个属性实际就是Object.defineProperty的三个参数,如果是类的属性,则没有传递第三个参数

如下例子:

// 声明装饰器修饰方法/属性
function method(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  console.log(target);
  console.log("prop " + propertyKey);
  console.log("desc " + JSON.stringify(descriptor) + "\n\n");
  descriptor.writable = false;
};

function property(target: any, propertyKey: string) {
  console.log("target", target)
  console.log("propertyKey", propertyKey)
}

class Person{
 @property
 name: string;
 constructor() {
   this.name = 'huihui';
 }

 @method
 say(){
   return 'instance method';
 }

 @method
 static run(){
   return 'static method';
 }
}

const xmz = new Person();

// 修改实例方法say
xmz.say = function() {
 return 'edit'
}

输出如下图所示:

参数装饰

接收3个参数,分别是:

  • target :当前对象的原型
  • propertyKey :参数的名称
  • index:参数数组中的位置
function logParameter(target: Object, propertyName: string, index: number) {
  console.log(target);
  console.log(propertyName);
  console.log(index);
}

class Employee {
  greet(@logParameter message: string): string {
      return `hello ${message}`;
  }
}
const emp = new Employee();
emp.greet('hello');

输入如下图:

访问器装饰

使用起来方式与方法装饰一致,如下:


function modification(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
  console.log(target);
  console.log("prop " + propertyKey);
  console.log("desc " + JSON.stringify(descriptor) + "\n\n");
};

class Person{
 _name: string;
 constructor() {
   this._name = 'huihui';
 }

 @modification
 get name() {
   return this._name
 }
}

装饰器工厂

如果想要传递参数,使装饰器变成类似工厂函数,只需要在装饰器函数内部再函数一个函数即可,如下:

function addAge(age: number) {
  return function(constructor: Function) {
    constructor.prototype.age = age
  }
}

@addAge(10)
class Person{
  name: string;
  age!: number;
  constructor() {
    this.name = 'huihui';
  }
}

let person = new Person();

执行顺序

当多个装饰器应用于一个声明上,将由上至下依次对装饰器表达式求值,求值的结果会被当作函数,由下至上依次调用,例如如下:

function f() {
    console.log("f(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("f(): called");
    }
}

function g() {
    console.log("g(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("g(): called");
    }
}

class C {
    @f()
    @g()
    method() {}
}

// 输出
f(): evaluated
g(): evaluated
g(): called
f(): called

三、应用场景

可以看到,使用装饰器存在两个显著的优点:

  • 代码可读性变强了,装饰器命名相当于一个注释
  • 在不改变原有代码情况下,对原来功能进行扩展

后面的使用场景中,借助装饰器的特性,除了提高可读性之后,针对已经存在的类,可以通过装饰器的特性,在不改变原有代码情况下,对原来功能进行扩展

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络质量探测

目录 一.BFD监测网络状态 二. NQA检测网络状态 一.BFD监测网络状态 BFD(BidrectionaL Forwarding Detection 双向转发检测)用于快速检测系统设备之间的发送和接受两个方向的通信故障,并在出现故障时通知生成应用。BFD 广泛用于链路故障检测,并能实现与…

Python画图之皮卡丘

Python-turtle画出皮卡丘(有趣小游戏) 一、效果图二、Python代码 一、效果图 二、Python代码 import turtledef getPosition(x, y):turtle.setx(x)turtle.sety(y)print(x, y)class Pikachu:def __init__(self):self.t turtle.Turtle()t self.tt.pensi…

在虚拟机centos7中部署docker+jenkins最新稳定版

在虚拟机centos7中部署dockerjenkins最新稳定版 查看端口是否被占用 lsof -i:80 查看运行中容器 docker ps 查看所有容器 docker ps -a 删除容器 docker rm 镜像/容器名称 强制删除 docker rmi -f 镜像名 查看当前目录 pwd 查看当前目录下所有文件名称 ls 赋予权限 chown 777 …

回归预测 | Matlab实现WOA-CNN-SVM鲸鱼算法优化卷积神经网络-支持向量机的多输入单输出回归预测

回归预测 | Matlab实现WOA-CNN-SVM鲸鱼算法优化卷积神经网络-支持向量机的多输入单输出回归预测 目录 回归预测 | Matlab实现WOA-CNN-SVM鲸鱼算法优化卷积神经网络-支持向量机的多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.WOA-CNN-SVM鲸鱼算法…

STM32-RTC实时时钟

目录 RTC实时时钟 功能框图 UNIX时间戳 初始化结构体 RTC时间结构体 RTC日期结构体 RTC闹钟结构体 进入和退出配置函数 实验环节1:显示日历 常规配置 RTC配置 测试环节 实验现象 实验环节2:闹钟 常规配置 RTC配置 测试环节 实验现象 R…

【C/C++】仿函数

函数调用运算符 () 也可以重载由于重载后使用的方式非常像函数的调用&#xff0c;因此称为仿函数仿函数没有固定写法&#xff0c;非常灵活 示例&#xff1a; #include <iostream> #include <string> using namespace std;class MyPrint { public://重载的运算符是…

Antlr4学习笔记

背景 在阅读shardingjdbc-4.1.1代码时&#xff0c;发现一段sql解析的逻辑&#xff0c;好奇它的实现&#xff0c;查阅相关资料发现解析引擎基于Antlr4实现&#xff0c;便有了此文 官方文档中也描述了解析引擎的迭代过程 SQL解析作为分库分表类产品的核心&#xff0c;其性能和兼…

VSCode 如何设置背景图片

VSCode 设置背景图片 1.打开应用商店&#xff0c;搜索 background &#xff0c;选择第一个&#xff0c;点击安装。 2. 安装完成后点击设置&#xff0c;点击扩展设置。 3.点击在 settings.json 中编辑。 4.将原代码注释后&#xff0c;加入以下代码。 // { // "workben…

第4章_运算符

文章目录 1. 算术运算符1.1 加法与减法运算符1.2 乘法与除法运算符1.3 求模运算符 2. 比较运算符2.1 等号运算符2.2 安全等于运算符2.3 不等于运算符2.4 空运算符2.5 非空运算符2.6 最小值运算符2.7 最大值运算符2.8 BETWEEN AND运算符2.9 IN运算符2.10 NOT IN运算符2.11 LIKE运…

Mysql用sql查询数字四舍五入小数点后两位并且第二位如果没有数用0填补

表中数据小数点后几位好长&#xff0c;直接上图 核心sql REPLACE(FORMAT(ROUND(d2.jiner, 2), 2), ,, ) ROUND函数处理数字四舍五入 FORMAT处理小数点后面必须跟进两位&#xff0c;也就是第二位没数字的话用0填补 REPLACE处理将逗号全部去除&#xff0c;因为FORMAT会导致数字…

苹果相机怎么磨皮 苹果手机怎么磨皮

相信使用苹果相机的小伙伴都有这样的疑惑&#xff0c;苹果相机怎么磨皮&#xff1f;其实可以通过相机的参数进行设置从而达到磨皮的效果&#xff0c;如果觉得相机自带的设置磨皮效果不够好&#xff0c;可以下载磨皮软件来对照片磨皮。今天的文章就来给大家介绍苹果相机怎么磨皮…

【嵌入式项目应用】__cJSON基础介绍与代码测试

目录 前言 一、JSON是什么&#xff1f; 1. JSON 基本语法 2. JSON值(value)的类型 3. 逻辑值&#xff08;true 或 false&#xff09; 4. null 5. NUMBER 数字&#xff08;整数或浮点数&#xff09; 6. STRING 字符串&#xff08;在双引号""中&#xff09; 7…

在NestJS应用程序中使用 Unleash 实现功能切换的指南

前言 近年来&#xff0c;软件开发行业迅速发展&#xff0c;功能开关&#xff08;Feature Toggle&#xff09;成为了一种常见的开发实践。通过功能开关&#xff0c;可以在运行时动态地启用或禁用应用程序的特定功能&#xff0c;以提供更灵活的软件交付和配置管理。对于使用 Nes…

手把手教你使用Vue2.0实现动态路由展示

文章目录 VUE2相关组件版本原始菜单数据数据库数据树形数据 前端项目配置静态路由配置路由守卫左侧路由回显代码 使用Vue2实现动态路由展示 思路&#xff1a; 后端返回树形数据根据数据渲染左侧菜单根据数据组装路由数据 注意&#xff1a;本文主要目的讲解是一种思路&#xff0…

阿里云推出AI编程工具“通义灵码“;生成式 AI 入门教程 2

&#x1f989; AI新闻 &#x1f680; 阿里云推出AI编程工具"通义灵码"&#xff0c;支持多种语言及实时续写功能 摘要&#xff1a;阿里云推出了一款名为"通义灵码"的AI编程工具&#xff0c;支持多种主流编程语言&#xff0c;包括Java、Python、Go等。该工…

找到数组中出现一种/两种奇数——异或运算

找到数组中出现一种/两种奇数 题目&#xff1a;一个数组有一种数出现了奇数次&#xff0c;其他数都出现了偶数次&#xff0c;怎么找到并打印这个数&#xff1f; trick 因为异或运算有个特点&#xff0c;满足交换律和结合律&#xff0c;同时有两个重要的特点&#xff1a; n^n…

Xray+awvs联动扫描

首先xray开启监听 xray_windows_amd64.exe webscan --listen 127.0.0.1:7777 --html-output xray-xxx.html --plugins sqldet,xxe,upload,brute-force,cmd-injection,struts,thinkphp 然后准备目标csv文件,每行一个url或ip然后加个逗号 接着awvs导入csv 对导进来的每个目…

沉痛悼念科研分公司

今天上班途中&#xff0c;遇到了上家公司的同事王强。他正准备去体检中心体检。几句寒暄之后&#xff0c;得知他是要入职选煤公司了。 我们所在的公司比较大&#xff0c;总公司下设有几十个分、子公司&#xff0c;我和他曾经在一家子公司——科研分公司。现在的科研分公司解散…

FIFO 位宽转换

从8位转32位 module tb_fifo();reg clk,rst; initial beginclk0;forever #4.545 clk~clk; end initial beginrst1;#9.09 rst0; endreg [31:0] cnts; always (posedge clk or posedge rst) beginif(rst)begincnts < 32d0;endelsebegincnts < cnts 1b1;end endreg […

中国电子云-隐私计算-云原生安全可信计算,物理-硬件-系统-云产品-云平台,数据安全防护

目录 联邦学习的架构思想 中国电子云-隐私计算-云原生安全 可信计算&#xff0c;物理-硬件-系统-云产品-云平台&#xff0c;数据安全防护 全栈国产信创的意义 1. 提升科技创新能力 2. 推动经济发展 3. 加强信息安全与自主可控 全栈国产信创的重要领域 1. 人工智能 2.…