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

担路网提供网站建设广州关键词优化外包

担路网提供网站建设,广州关键词优化外包,云南网络营销文化优化,宁波如何做抖音seo搜索优化目录 一. 简介 二. 类装饰器 1. 基本语法 2. 应用举例 3. 关于返回值 4. 关于构造类型 5. 替换被装饰的类 三. 装饰器工厂 四. 装饰器组合 五. 属性装饰器 1. 基本语法 2. 关于属性遮蔽 3. 应用举例 六. 方法装饰器 1. 基本语法 2. 应用举例 七. 访问器装饰器 …

目录

一. 简介

二. 类装饰器

1. 基本语法

2. 应用举例

3. 关于返回值

4. 关于构造类型

5. 替换被装饰的类

三. 装饰器工厂

四. 装饰器组合

五. 属性装饰器

1. 基本语法

2. 关于属性遮蔽

3. 应用举例

六. 方法装饰器

1. 基本语法

2. 应用举例

七. 访问器装饰器

1. 基本语法

2. 应用举例

八. 参数装饰器

1. 基本语法

2. 应用实例


一. 简介
  1. 装饰器本质是一种特殊的函数,它可以对 : 类 , 属性 , 方法 , 参数进行扩展,同时让代码更简洁

  2. 装饰器自2015年在ECMAScript中被提出到现在,已将近10年

  3. 截至目前,装饰器依然是实验性特性,需要开发者手动调整配置,来开启装饰器支持

  4. 装饰器有5种 :

    (1)类装饰器

    (2)属性装饰器

    (3)方法装饰器

    (4)访问器装饰器

    (5)参数装饰器

备注 : 虽然TypeScript5.0中可以直接使用类装饰器,但为了确保其他装饰器可用,现阶段使用时,仍建议使用experimentalDecorators配置来开启装饰器支持,而且不排除未来的版本中官方会进一步调整装饰器的相关语法 !

二. 类装饰器
1. 基本语法

类装饰器是一个应用再类声明上的函数,可以为类添加额外的功能,或添加额外的逻辑

/*Demo函数会在Person类定义时执行参数说明:target参数是被装饰的类,即Person
*/
function Demo(target: any) {console.log(target);
​
}
​
@Demo
class Person {name: stringage: numberconstructor(name: string, age: number) {this.name = namethis.age = age}
}
2. 应用举例

需求 : 定义一个装饰器,实现Person实例调用toString时返回JSON.stringify的执行结果

function CustomString(target:Function){target.prototype.toString = function(){return JSON.stringify(this)}Object.seal(target.prototype)
}
​
@CustomString
class Person {name: stringage: numberconstructor(name: string, age: number) {this.name = namethis.age = age}
}
const p1 = new Person('张三',18)
console.log(p1.toString())
3. 关于返回值
  • 类装饰器返回值 : 若类装饰器返回一个新的类,那这个新类将替换掉被装饰的类

  • 类装饰器返回值 : 若类装饰器无返回值或返回undefined,那被装饰的类不会被替换

function Demo(target: Function) {return class {test() {console.log(100);console.log(200);console.log(300);}}
}
​
@Demo
class Person {test() {console.log(100);}
}
​
console.log(Person);
4. 关于构造类型

在TypeScript中,Function类型所表示的范围十分广泛,包括 : 普通函数,箭头函数,方法等等,但并非Function类型的函数都可以被new关键字实例化,例如箭头函数是不能被实例化的,那么TypeScript中该如何声明一个构造类型呢?有以下两种方式:

  • 仅声明构造类型

/*
new表示:该类型是可以用new操作符调用
...args表示:构造器是可以接受[任意数量]的参数
any[]表示:构造器可以接受[任意类型]的参数
{}表示:返回类型是对象(非null,非undefined的对象)
*/
​
type Constructor = new (...args: any[]) => {}
//需求是fn得是一个类
function test(fn: Constructor) { }
​
class Person { }
​
test(Person)
  • 声明构造类型 + 指定静态属性

type Constructor = {new(...args: any[]): {}wife: string
}
//需求是fn得是一个类
function test(fn: Constructor) { }
​
class Person { static wife:string
}
​
test(Person)
5. 替换被装饰的类

对于高级一些的装饰器,不仅仅是覆盖一个原型上的方法,还要有更多功能,例如添加新的方法和状态

需求 : 设计一个LogTime装饰器,可以给实例添加一个属性,用于记录实例对象的创建时间,再添加一个方法用于读取创建时间

type Constructor = new (...args: any[]) => {}
​
interface Person {getTime(): void
}
function LogTime<T extends Constructor>(target: T) {return class extends target {createdTime: Dateconstructor(...args: any[]) {super(...args)this.createdTime = new Date()}getTime() {return `该对象的创建时间是:${this.createdTime}`}}
}
​
​
@LogTime
class Person {constructor(public name: string, public age: number) {this.name = namethis.age = age}speak() {console.log('你好呀!');}
}
​
const p1 = new Person('张三', 18)
console.log(p1);
console.log(p1.getTime());
三. 装饰器工厂

装饰器工厂是一个返回装饰器函数的函数,可以为装饰器添加参数,可以更灵活地控制装饰器的行为

需求 : 定义一个LogInfo类装饰器工厂,实现Person实例可以调用到introduce方法,且introduce中输出内容的次数,由LogInfo接收的参数决定

interface Person{introduce():void
}
​
function LogInfo(n:number) {return function(target:Function){target.prototype.introduce = function(){for(let i = 0;i < n;i++){console.log(`我的名字:${this.name},我的年龄:${this.age}`);}}}//装饰器
}//装饰器工厂
​
​
@LogInfo(3)
class Person {constructor(public name: string,public age: number) { }speak() {console.log('你好呀!');}
}
​
const p1 = new Person('张三',18)
p1.introduce()
四. 装饰器组合

装饰器可以组合使用,执行顺序为:先[由上到下]的执行所有的装饰器工厂,依次获取到装饰器,然后再[由下到上]执行所有的装饰器

  • 装饰器组合的执行顺序

//装饰器
function test1(target:Function) {console.log('test1');
}
​
//装饰器工厂
function test2() {console.log('test2工厂');return function (target:Function) {console.log('test2');}
}
​
//装饰器工厂 
function test3() {console.log('test3工厂');return function (target:Function) {console.log('test3');}
}
​
//装饰器
function test4(target:Function) {console.log('test4');
}
​
@test1
@test2()
@test3()
@test4
class Person{}

  • 装饰器组合的应用

interface Person {introduce(): voidgetTime(): void
}
function CustomString(target: Function) {//使用装饰器重写toString方法 + 封闭其原型对象target.prototype.toString = function () {return JSON.stringify(this)}Object.seal(target.prototype)
}//装饰器
​
function LogInfo(n: number) {//装饰器函数:target是被装饰的类return function (target: Function) {target.prototype.introduce = function () {for (let i = 0; i < n; i++) {console.log(`我的名字:${this.name},我的年龄:${this.age}`);}}}//装饰器
}//装饰器工厂
​
type Constructor = new (...args: any[]) => {}
function LogTime<T extends Constructor>(target: T) {return class extends target {createdTime: Dateconstructor(...args: any[]) {super(...args)this.createdTime = new Date()}getTime() {return `该对象的创建时间是:${this.createdTime}`}}
}//装饰器
​
@CustomString
@LogInfo(5)
@LogTime
class Person {constructor(public name: string,public age: number) { }speak() {console.log('你好呀!');}
}
​
const p1 = new Person('张三', 18)
p1.speak()
console.log(p1.toString());
p1.introduce()
console.log(p1.getTime());

五. 属性装饰器
1. 基本语法
function Demo(target:object,propertyKey:string){console.log(target,propertyKey) ;
}
​
/*参数说明:target : 对于静态属性来说值是类,对于实例属性来说值是类的原型对象{}propertyKey : 属性名
*/
​
class Person {@Demo name: string@Demo age: number@Demo static school: stringconstructor(name: string, age: number) {this.name = namethis.age = age}
}

2. 关于属性遮蔽

如下代码中 : 当构造器中的this.age = age试图在实例上赋值时,实际上时调用了原型上age属性的set方法

class Person {name: stringage: numberstatic school: stringconstructor(name: string, age: number) {this.name = namethis.age = age}
}
​
let value = 130
Object.defineProperty(Person.prototype, 'age', {get() {return value},set(val) {value = val},
})
​
const p1 = new Person('张三', 18)
console.log(p1.age);//18
console.log(Person.prototype.age);//18
3. 应用举例

需求 : 定义一个State属性装饰器,来监视属性的修改

function State(target: object, propertyKey: string) {let key = `__${propertyKey}`Object.defineProperty(target, propertyKey, {get() {return this[key]},set(newValue) {console.log(`${propertyKey}的最新值为:${newValue}`);this[key] = newValue},//还可以加上两个配置项enumerable: true,//可枚举性configurable: true,//可配置性})
}
​
class Person {name: string@State age: numberconstructor(name: string, age: number) {this.name = namethis.age = age}
}
​
const p1 = new Person('张三', 18)
六. 方法装饰器
1. 基本语法
/*参数说明:target:对于静态方法来说值是类,对于实例方法来说值是原型对象propertyKey:方法的名称descriptor:方法的描述对象,其中value属性是被装饰的方法
*/
​
​
function Demo(target:object,propertyKey:string,descriptor:PropertyDescriptor){console.log(target);console.log(propertyKey);console.log(descriptor);
}
​
class Person {constructor(public name: string,public age: number,) { }@Demospeak() {//实例方法console.log(`你好,我的名字:${this.name},我的年龄:${this.age}`);}@Demostatic isAdult(age: number) {//静态方法return age >= 18;}
} 
​
const p1 = new Person('张三',18)
p1.speak()
2. 应用举例

定义一个Logger方法装饰器,用于在方法执行前和执行后,均追加一些额外逻辑

function Logger(target:object,propertyKey:string,descriptor:PropertyDescriptor){//存储原始方法const originnal = descriptor.value//替换原始方法descriptor.value = function(...args:any[]){console.log(`${propertyKey}开始执行......`);const result = originnal.call(this,...args) console.log(`${propertyKey}执行完毕......`);return result}
​
}
​
class Person {constructor(public name: string,public age: number,) { }@Logger speak(str:string) {//实例方法console.log(`你好,我的名字:${this.name},我的年龄:${this.age},${str}`);}static isAdult(age: number) {//静态方法return age >= 18;}
} 
​
const p1 = new Person('tom',18)
p1.speak('hello')

定义一个Validate方法装饰器,用于验证数据

function Logger(target:object,propertyKey:string,descriptor:PropertyDescriptor){//存储原始方法const originnal = descriptor.value//替换原始方法descriptor.value = function(...args:any[]){console.log(`${propertyKey}开始执行......`);const result = originnal.call(this,...args) console.log(`${propertyKey}执行完毕......`);return result}
​
}
​
function Validate(maxValue:number){return function(target:object,propertyKey:string,descriptor:PropertyDescriptor){//保存原始方法const originnal = descriptor.value//替换原始方法descriptor.value = function(...args:any[]){//自定义的验证逻辑if(args[0] > maxValue){throw new Error('年龄非法')}//如果所有参数都符合要求,则使用原始方法return originnal.apply(this,args)}}
}
​
class Person {constructor(public name: string,public age: number,) { }@Logger speak(str:string) {//实例方法console.log(`你好,我的名字:${this.name},我的年龄:${this.age},${str}`);}@Validate(120)static isAdult(age: number) {//静态方法return age >= 18;}
} 
​
const p1 = new Person('tom',18)
p1.speak('hello')
console.log(Person.isAdult(100));
七. 访问器装饰器
1. 基本语法
/*参数说明target:1.对于实例访问器来说是[所属类的原型对象]2.对于静态访问器来说值是[所属类]propertyKey:访问器名称descriptor:描述对象
*/
function Demo(target: object, propertyKey: string, descriptor: PropertyDescriptor) {console.log(target);console.log(propertyKey);console.log(descriptor);
}
​
class Person {@Demoget address() {return '涩谷'}//实例访问器@Demostatic get country() {return 'Japan'}//静态访问器
}
2. 应用举例

需求 : 对Weather类的temp属性的set访问器进行限制,设置的最低温度-50,最高温度50

function RangeValidate(min:number,max:number){return function(target:object,propertyKey:string,descriptor:PropertyDescriptor){//保存原始的setterconst originalSetter = descriptor.set//重写setterdescriptor.set = function(value:number){//检查设置的值是否在指定的最小值和最大值之间if(value < min||value > max){//如果值不在范围内,抛出错误throw new Error(`${propertyKey}的值应该在${min}到${max}之间`);}//如果值在范围内,且原始setter方法存在,则调用原始setter方法if(originalSetter){originalSetter.call(this,value);}}}
}
​
class Weather {private _temp: number;constructor(_temp:number) {this._temp = _temp;}@RangeValidate(-50,50)set temp(value) {this._temp = value;}get temp() {return this._temp;}
}
​
const w1 = new Weather(28)
w1.temp = 9000
console.log(w1);

八. 参数装饰器
1. 基本语法
/*参数说明:target:1.如果修饰的是[实例方法]的参数,target是类的[原型对象]2.如果修饰的是[静态方法]的参数,target是[类]propertyKey:参数所在的方法的名称parameterIndex:参数在函数参数列表中的索引,从0开始
*/
function Demo(target: object, propertyKey: string, parameterIndex: number) {console.log(target);console.log(propertyKey);console.log(parameterIndex);
}
​
//类定义
class Person {constructor(public name: string) { }speak(@Demo message1: any, message2: any) {console.log(`${this.name}想对你说:${message1},${message2}`);}
}
2. 应用实例

需求 : 定义方法装饰器Validate,同时搭配参数装饰器NotNumber,来对speak方法的参数类型进行限制

function NotNumber(target: any, propertyKey: string, parameterIndex: number) {// 初始化或获取当前方法的参数索引列表let notNumberArr: number[] = target[`__notNumber_${propertyKey}`] || [];// 将当前参数索引添加到列表中notNumberArr.push(parameterIndex);// 将列表存储回目标对象target[`__notNumber_${propertyKey}`] = notNumberArr;}// 方法装饰器定义function Validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {const method = descriptor.value;descriptor.value = function (...args: any[]) {// 获取被标记为不能为空的参数索引列表const notNumberArr: number[] = target[`__notNumber_${propertyKey}`] || [];// 检查参数是否为 null 或 undefinedfor (const index of notNumberArr) {if (typeof args[index] === 'number') {throw new Error(`方法 ${propertyKey} 中索引为 ${index} 的参数不能是数字!`)}}// 调用原始方法return method.apply(this, args);};return descriptor;}// 类定义class Student {name: string;constructor(name: string) {this.name = name;}@Validatespeak(@NotNumber message1: any, message2: any) {console.log(`${this.name}想对说:${message1},${message2}`);}}// 使用const s1 = new Student("张三");s1.speak(100, 200);

http://www.dtcms.com/wzjs/489907.html

相关文章:

  • 横岗网站建设多少钱农产品营销方案
  • 给女朋友做的网站内容建设官网的网站首页
  • 视频网站中滑动列表怎么做北京seo网站优化公司
  • 武汉教育网站建设优化百度推广产品有哪些
  • 怎么做淘宝客网站备案潍坊网站seo
  • 域名访问过程会不会影响网站访问免费建立网站步骤
  • 西安 网站建设 培训学校建立网站的基本步骤
  • 合肥门户网站制作建设seo排名app
  • 2021网页游戏排行windows7优化大师官方下载
  • 电脑手机一体网站竞价账户托管哪家好
  • 高端企业网站价位淘宝指数转换工具
  • 在网站做直播做一个网站需要什么
  • 白城学做网站百度热搜风云榜
  • 三站一体网站制作百度热词指数
  • 免费wap网站建设网络广告营销案例分析
  • 专做排版网站百度seo软件曝光行者seo
  • 当前网站开发的现状百度推广客户端下载安装
  • 做标识的网站 知乎百度关键词搜索排名代发
  • 镇江个人网站建设产品推广计划
  • beego做网站西安网络科技有限公司
  • 网站优化怎么做关键词排名学生个人网页制作教程
  • 以后做网站发展前途南京seo
  • 营销策划公司有哪些公司杭州seo搜索引擎优化公司
  • 关于网站及新媒体平台建设的规划百度推广外推联系方式
  • 北京 网站备案利用搜索引擎营销成功的案例
  • 网站可以做的兼职怎么推广网站链接
  • 快速网站制作西安疫情最新通知
  • 做日本民宿的网站中国国家培训网靠谱吗
  • wordpress可以装在子目录下潜江seo
  • aspx网站使用什么做的百度知道网页版入口