一、是什么

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

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

同样的,本质也不是什么高大上的结构,就是一个普通的函数,@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 中装饰器的理解?应用场景?的更多相关文章

  1. TypeScript 素描 - 装饰器

    /* 装饰器 简单理解为C#中的Attribute 可以装饰到类.函数.讯问符.属性.参数上 语法 @xxx 装饰器其实是一个函数 @xxx 就要有一个 function xxx 多个装饰器可以用来装 ...

  2. 转发对python装饰器的理解

    [Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考   原文  http://blog.csdn.net/sxw3718401/article/details/3951958 ...

  3. python中装饰器使用

    装饰器是对已有的模块进行装饰(添加新功能)的函数. 现有一段代码: import time def func1(): time.sleep(3) print("in the func1&qu ...

  4. Python - 关于带参数的装饰器的理解

    [原创]转载请注明作者Johnthegreat和本文链接 关于装饰器的理解,特别像<盗梦空间>中的进入梦境和从梦境出来的过程,一层一层的深入梦境,然后又一层一层的返回,被带入梦境的是被装饰 ...

  5. 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法

    第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法 上节介绍了Python中类的静态方法,本节将结合案例详细说明相关内容. 一.    案例说明 本节定义了类Sta ...

  6. 8.Python中装饰器是什么?

    Python中装饰器是什么? A Python decorator is a specific change that we make in Python syntax to alter functi ...

  7. python中对变量的作用域LEGB、闭包、装饰器基本理解

    一.作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量 ...

  8. python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)

    转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...

  9. python中装饰器你真的理解吗?

    def w1(func): print('装饰器1....') def w1_in(): print('w1_in.....') func() return w1_in def w2(func): p ...

随机推荐

  1. Python 机器学习实战 —— 无监督学习(下)

    前言 在上篇< Python 机器学习实战 -- 无监督学习(上)>介绍了数据集变换中最常见的 PCA 主成分分析.NMF 非负矩阵分解等无监督模型,举例说明使用使用非监督模型对多维度特征 ...

  2. .net 知新:【4】NuGet简介和使用

    在包管理以前我们在项目中引用第三方包通常是去下载dll放到项目中再引用,后来逐渐发展成各种包管理工具,nuget就是一种工具,适用于任何现代开发平台的基本工具可充当一种机制,通过这种机制,开发人员可以 ...

  3. SunOS与Solaris系统的对应关系

    下文绝大部分译自维基百科Solaris词条的"历史"部分: http://en.wikipedia.org/wiki/Solaris_(operating_system)#Hist ...

  4. shell——sort、uniq、tr、cut和eval命令

    一.排序命令sort 以行位单位对文件内容进行排序,也可以根据不同的数据类型进行排序 格式:sort [选项] 参数 格式:cat file | sort 选项 1.2常用选项 选项说明 -f 忽略大 ...

  5. MySQL高级查询 & 事务机制

    1.基础查询where 高级条件查询Where子句 SELECT empno,ename,sal,hiredate FROM t_tmp WHERE deptno=10 AND (sal+IFNULL ...

  6. Shell-05-函数

    函数 函数定义 shell中函数的定义格式如下 [ function ] funname [()] { action; [return int;] } 说明: 1.可以带function fun() ...

  7. 手把手和你一起实现一个Web框架实战——EzWeb框架(四)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(四)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 这一篇文章主要实现路由组功能.实现路由 ...

  8. SQL注入之MySQL报错注入整理

    看大佬们的文章看得我虎躯一震,精神抖擞,于是心血来潮,整理一下MySQL报错注入常见的手段和方法,再举几个例子 <代码审计:企业级Web代码安全架构>一书中介绍过报错注入十大方法,依次是: ...

  9. 尝试通过 JDBC 将 UTF-8 插入 MySQL 时出现“乱码”

    这是我的连接设置方式: Connection conn = DriverManager.getConnection(url + dbName + "?useUnicode=true& ...

  10. noip34

    因为改不动T3而来水博客的屑 昨晚没睡好,大致看了一遍题面后,选择了死亡231,然后就死的很惨. T1 一开始大致看题面的时候,就略了一眼,加上没读全题,啥思路也没有,最后四十分钟滚回来看了看,发现就 ...