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
三、应用场景
可以看到,使用装饰器存在两个显著的优点:
- 代码可读性变强了,装饰器命名相当于一个注释
- 在不改变原有代码情况下,对原来功能进行扩展
后面的使用场景中,借助装饰器的特性,除了提高可读性之后,针对已经存在的类,可以通过装饰器的特性,在不改变原有代码情况下,对原来功能进行扩展
TypeScript 中装饰器的理解?应用场景?的更多相关文章
- TypeScript 素描 - 装饰器
/* 装饰器 简单理解为C#中的Attribute 可以装饰到类.函数.讯问符.属性.参数上 语法 @xxx 装饰器其实是一个函数 @xxx 就要有一个 function xxx 多个装饰器可以用来装 ...
- 转发对python装饰器的理解
[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考 原文 http://blog.csdn.net/sxw3718401/article/details/3951958 ...
- python中装饰器使用
装饰器是对已有的模块进行装饰(添加新功能)的函数. 现有一段代码: import time def func1(): time.sleep(3) print("in the func1&qu ...
- Python - 关于带参数的装饰器的理解
[原创]转载请注明作者Johnthegreat和本文链接 关于装饰器的理解,特别像<盗梦空间>中的进入梦境和从梦境出来的过程,一层一层的深入梦境,然后又一层一层的返回,被带入梦境的是被装饰 ...
- 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法
第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法 上节介绍了Python中类的静态方法,本节将结合案例详细说明相关内容. 一. 案例说明 本节定义了类Sta ...
- 8.Python中装饰器是什么?
Python中装饰器是什么? A Python decorator is a specific change that we make in Python syntax to alter functi ...
- python中对变量的作用域LEGB、闭包、装饰器基本理解
一.作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量 ...
- python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)
转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...
- python中装饰器你真的理解吗?
def w1(func): print('装饰器1....') def w1_in(): print('w1_in.....') func() return w1_in def w2(func): p ...
随机推荐
- matlab快速入门
matlab快速入门 1矩阵 生成矩阵 % 直接法 a = [1,2,3;4,5,6;7,8,9]; % 冒号一维矩阵 a = 开始:步长:结束,步长为1可省略 b = 1:1:10; % 1,2 ...
- Flink EOS如何防止外部系统乱入--两阶段提交源码
一.前言 根据维基百科的定义,两阶段提交(Two-phase Commit,简称2PC)是巨人们用来解决分布式系统架构下的所有节点在进行事务提交时保持一致性问题而设计的一种算法,也可称之为协议. 在F ...
- 【Java笔记】以并发修改异常为例总结的出错解决办法
先来看出错代码: /*需求: 遍历已有集合 如果在集合中发现存在字符串元素"world" 则在"world"后添加元素"javaee" */ ...
- CVE-2020-17523:Apache Shiro身份认证绕过漏洞分析
0x01 Apache Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 0x02 漏洞简介 2021年2月1日,Apache Shiro官 ...
- 生成二维码项目pom.xml中QRCode依赖报错
pom.xml报错如下: 解决方法: 1.将QRCode.jar包下载到E盘下 网盘下载地址: 链接:https://pan.baidu.com/s/1sY1NK5ekCkNH0uqraZMnKw 提 ...
- Java虚拟机漫漫学习路,我终于悟了
毕业8年,前5年的职业规划是做计算广告,后来感觉计算广告这一行更注重的是业务而非技术,而自己的性格更适合做技术,所以毅然决然的辞职, 全职1年半时间写了2本关于Java编译器与虚拟机的书,今年年初来到 ...
- ThreadPoolExecutor(线程池)的参数
构造函数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit u ...
- spring boot 的JPA项目
pom 文件 -------------------------------------------------------------------------- <dependencies&g ...
- Java知识图谱(附:阿里Java学习计划)
摘要: 本文主要描绘了Java基础学习过程,给出Java知识结构图,以及阿里Java岗学习计划,对Java学习爱好者.准备及将要从事Java开发方面的同学大有裨益. 温馨提示: 由于C ...
- 微信小程序学习笔记二 数据绑定 + 事件绑定
微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...