黑马程序员技术交流社区
标题: 【广州前端首发】TypeScript核心课程笔记(五) [打印本页]
作者: AreYouGlad 时间: 2017-12-15 16:37
标题: 【广州前端首发】TypeScript核心课程笔记(五)
本帖最后由 AreYouGlad 于 2017-12-20 11:53 编辑
装饰器
简介
装饰器的作用主要是用来修饰类行为的, 这就像它的名字一样, 给别人来个锦上添花
这个特性同样来自其他语言, 目前ECMA也有一个提案要把这项功能融入js当中, 未来有很大可能被正式采纳
编译说明
由于装饰器还没有正式成为ECMA标准, 未来可能还会有些许变化
所以要在ts中使用它需要添加experimentalDecorators编译选项
同时还要指明编译后的ES版本大于等于5, 因为装饰器会用到ES5中的特性, 否则转换后的代码会有问题
使用编译命令: tsc 文件名.ts --target ES5 --experimentalDecorators
或者先写好配置文件, 然后直接运行tsc命令, 根据配置文件进行编译
使用说明目前装饰器只能应用与类/实例与静态成员身上
应用在类上, 装饰器函数可以自动接收一个参数: 类
应用在静态方法上, 装饰器函数可以自动接收三个参数: 类 属性名 描述对象
应用在静态属性上, 装饰器函数可以自动接收两个参数: 类 属性名
应用在实例方法上, 装饰器函数可以自动接收三个参数: 原型 属性名 描述对象
应用在实例属性上, 装饰器函数可以自动接收两个参数: 原型 属性名
初探装饰器
装饰器本质就是一个函数,内部封装了一些用以修饰别人的公共处理逻辑,
装饰器的语法就是在要修饰的东西前面使用@符号调用函数
装饰器语法[AppleScript] 纯文本查看 复制代码
function decoratorFn(...arg: any[]) {
console.log('我执行了, 并且我自动收到了下面的东西!');
console.log(arg);
}
// 写法1: 在类的前一行使用装饰器
@decoratorFn
class Test {}
// 写法2: 在类前面的使用装饰器
@decoratorFn class Test2 {}
装饰属性与方法[AppleScript] 纯文本查看 复制代码
function decoratorFn(...arg: any[]) {
console.log('我执行了, 并且我自动收到了下面的东西!');
console.log(arg);
}
class Test {
@decoratorFn
static staticProp: string = '静态属性';
@decoratorFn
static staticFn(): void {
console.log('静态方法');
}
@decoratorFn
instanceProp: string = '实例属性';
@decoratorFn
instanceFn(): void {
console.log('实例方法');
}
}
装饰器作用
装饰类[AppleScript] 纯文本查看 复制代码
// 增强类的静态成员
function addFeature(target: any): void {
let newFeature = ['拉', '撒', '睡'];
if(target.feature) {
target.feature.push(...newFeature);
}
}
@addFeature
class Person {
static feature: string[] = ['吃', '喝'];
}
@addFeature
class Cat {
static feature: string[] = ['吃', '喝'];
}
// 测试
console.log(Person.feature); // ['吃', '喝', '拉', '撒', '睡']
console.log(Cat.feature); // ['吃', '喝', '拉', '撒', '睡']
装饰器优点装饰器的好处是在无需做任何变动的情况下实现了功能增强
装饰器也是复用的另外一种形式, 装饰器的特点是目的性很强, 在多人项目中很容易让别人看懂你的意图
下面是不用装饰器的代码, 仍然可以实现相同的功能, 但无论是代码还是语义, 都不如装饰器优雅
[AppleScript] 纯文本查看 复制代码
function feature(target: any): void {
target.feature = ['吃', '喝', '拉', '撒', '睡'];
}
class Person {}
class Dog {}
// 实现了和装饰器同样的效果, 但是写起来明显不如装饰器语法来的简单
// 同时语义上无法直观的看出调用feature方法是为了增强类, 谁知道feature内部干了什么
feature(Person);
feature(Dog);
装饰方法在方法上使用装饰器, 装饰函数会自动接收到三个值: (类|原型) 方法名 描述对象
静态方法第一个参数为类, 实例方法第一个参数为原型
拿到这些值后, 我们可以修改或者替换方法定义
[AppleScript] 纯文本查看 复制代码
function executeTime(target: any, name: string, msg: any): void {
// 缓存旧方法
let oldFn = msg.value;
// 赋值新方法, 新方法对旧方法进行了功能扩展
msg.value = function(...arg: any[]) {
let date = Date.now();
oldFn.call(this, ...arg);
console.log(`执行了: ${Date.now() - date} 毫秒`);
}
}
class Person {
@executeTime
static getTotal(): void {
console.log('70亿');
}
@executeTime
study(time: number): void {
for(let i =0; i < time; i++) {
console.log('学习');
}
}
}
// 测试
new Person().study(1000);
Person.getTotal()
装饰属性在属性上使用装饰器, 装饰函数会自动接收到两个值: (类|原型) 方法名
静态属性第一个参数为类, 实例属性第一个参数为原型
[AppleScript] 纯文本查看 复制代码
function getSet(...arg: any[]): void {
let classOrPrototype = arg[0]; // 类或原型
let propName = arg[1]; // 属性名称
// 根据属性名称添加对应的set方法
classOrPrototype[propName + 'Set'] = function(val: any): void {
this[propName] = val;
}
// 根据属性名称添加对应的get方法
classOrPrototype[propName + 'Get'] = function(): any {
return this[propName];
}
}
class Person {
@getSet
name: string = '匿名';
@getSet
static total: number = 0;
}
// 测试
Person.totalSet(100);
Person.totalGet();
let fang: Person = new Person();
fang.nameSet('芳芳');
fang.nameGet();
装饰器工厂 - 可传参的装饰器
语法
[AppleScript] 纯文本查看 复制代码
// 外层的函数可收到用户传递的参数
function test(param: string): any {
console.log(param);
// 内层函数可收到装饰器自动传递的参数, 说白了就是以前的装饰器函数
return function(target: any): void {
console.log(target);
}
}
// 这里的装饰器语法相比以前多了小括号调用与传参
@test('可以传参?')
class Person {}
// 装饰器工厂内部返回一个函数, 内部的函数就是我们之前写的装饰器函数
function getZhuangshiqi(a: number) {
// 这个装饰器函数可以自动接收到一些值, 因为我们这个案例装饰了类, 那么就应该得到一个类
return function(target: any) {
// 现在这个装饰器函数即可以使用用户传过来的参数, 也可以使用自动传过来的参数
console.log(a);
console.log(target);
}
}
// 用户现在可以调用传参
@getZhuangshiqi(123)
class Person{}
使用范例
[AppleScript] 纯文本查看 复制代码
function feature(level: string): any {
return function(target: any): void {
// 高等生物
if(level === '高等') {
target.feature.push('玩', '乐');
}
// 低等生物
else if(level === '低等') {
target.feature.push('拉', '撒');
}
}
}
@feature('高等')
class Person {
static feature: string[] = ['吃', '喝'];
}
@feature('低等')
class Dog {
static feature: string[] = ['吃', '喝'];
}
补充
[AppleScript] 纯文本查看 复制代码
function decorator1(...arg: any[]) {
console.log('装饰器1');
}
function decorator2(...arg: any[]) {
console.log('装饰器2');
}
function decorator3(...arg: any[]) {
console.log('装饰器3');
}
@decorator1
@decorator2
@decorator3
class Person {}
作者: AreYouGlad 时间: 2017-12-15 16:37
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |