装饰器

装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为

通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能

常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器

装饰器的写法:普通装饰器(无法传参)、装饰参数器工厂(可传参)

类装饰器

类装饰器在类声明之前被声明(紧靠着声明类型),类装饰器应用于类构造函数,可以用来监视,修改或替换类定义,

//定义一个装饰器
function loge(params:any){
    console.log(params)   //输出当前类
} 

@loge 
class box{
    constructor(){

    }
    get(){

    }
}

编译后的js文件

 

 

 

 我们可以在这params的原型链上添加方法或者属性,也就是给当前类的原型链上添加一个方法或者属性

//定义一个装饰器
function loge(params:any){
    console.log(params)
    params.prototype.url='***'
} 

@loge   //不能有分号,挨着定义的类
class box{
    constructor(){

    }
    get(){

    }
}
var box1=new box()
console.log(box1)
console.log(box1.url)

 

 装饰器工厂

function login(params:string){
    return function(target:any){
            console.log(target)
            console.log(params)        

    }
}
@login("hello")
class fun{
    constructor(){

    }
    get(){

    }
}

编译后的js文件

 

 

@login("hello")中的hello赋值于params,函数fun赋值于target

 

 此时可以在target的原型链上添加方法

function login(params:string){
    return function(target:any){
            target.prototype.url=params     

    }
}
@login("hello")
class fun{
    constructor(){

    }
    get(){

    }
}
var a=new fun()
console.log(a.url)

 

 类装饰器表达式会在运行时当做函数被调用,类的构造函数作为其唯一的参数

如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明

function login(params:any){
    console.log(params)
}
@login
class fun{
    api:string|undefined;
    constructor(){
        this.api="我是fun中的api"
    }
    get(){
        console.log(this.api)
    }
}
var a=new fun()
a.get()

 

 此时我们重载参数或者构造函数

比如我们现在可以在login中修改constructorapi的值

function login(params:any){
    console.log(params)
    return class extends params{
        api:any="我是修改的"
        get(){
            console.log("我是修改的get")
        }
    }
}
@login
class fun{
    api:string|undefined;
    constructor(){
        this.api="我是fun中的api"
    }
    get(){
        console.log(this.api)
    }
}
var a=new fun()
a.get()

 

 属性装饰器

 属性装饰器会在运行时当做函数调用,传入以下2个参数

 

//类装饰器
function login(params:any){
    return function(target:any){

    }
}
//属性装饰器
function log(params:any){
    return function(target:any,attr:any){

    }
}
@login("hello")
class fun{
    @log("word")
    api:string|undefined;
    constructor(){
        this.api="我是fun中的api"
    }
    get(){
    }
}
var a=new fun()
a.get()

此时可以看到输出

 

 attr就是属性的名称

target就是当前类原型对象

//类装饰器
function login(params:any){
    return function(target:any){
        // console.log(target)
        // console.log(params)
    }
}
//属性装饰器
function log(params:any){
    return function(target:any,attr:any){
    //    console.log(target)
    //    console.log(attr)
    target[attr]=params
    
    }
    
}
@login("hello")
class fun{
    @log("word")
    api:string|undefined;
    constructor(){
        
    }
    get(){
       console.log(this.api)
    }
}
var a=new fun()
a.get()

 方法装饰器

应用到方法,属性描述符上,可以用来监视,修改或替换方法定义

方法装饰会在运行时传入下列参数

  • 对于静态变量成员来说是类的构造函数,对于实例成员或是类的原型对象
  • 成员的名字
  • 成员的属性描述符
//方法装饰器
function login(params:any){
    return function(target:any,methodName:any,desc:any){
        console.log(target)   //如果这个方法是静态方法,那么输出的时类的构造函数,如果是实例成员,那就是原型对象
        console.log(methodName)   //方法名称
        console.log(desc)   //方法描述
    }
}
class http{
    url:any|undefined;
    constructor(){

    }
    @login("http://www.baidu.com")
    get(){
    }
}
var a=new http()
a.get()

 

 第一个参数输出一个原型对象,在这个原型对象上可以修改当前的这个类,扩展这个类的属性以及方法

第二个参数是当前方法的名称

第三个参数是描述信息,里面有当前的get方法

此时我们扩展一个属性和一个方法

//方法装饰器
function login(params:any){
    return function(target:any,methodName:any,desc:any){
        console.log(target)   //如果这个方法是静态方法,那么输出的时类的构造函数,如果是实例成员,那就是原型对象
        console.log(methodName)   //方法名称
        console.log(desc)   //方法描述
        target.api="*****"   //扩展属性
        target.run=function(){   //扩展方法
                console.log(run)
        }
    }
}
class http{
    url:any|undefined;
    constructor(){
    }
    @login("http://www.baidu.com")
    get(){
        console.log(this.url)
    }
}
var a:any=new http()
console.log(a.api)

 

 

 此时我们想要修改get方法,其实就是修改描述信息中desc.value

我们可以看一下

 console.log(desc.value)

 

此时输出的这个方法就是get方法

方法修饰器可以修改当前的方法,可以把方法里面传入的参数改成string类型

//装饰器
function login(params:any){
    return function(target:any,methodName:any,desc:any){
        //console.log(target)   //如果这个方法是静态方法,那么输出的时类的构造函数,如果是实例成员,那就是原型对象
       // console.log(methodName)   //方法名称
       // console.log(desc.value)   //方法描述
        //修改这个装饰器的方法,把装饰器方法里面传入的所有参数改为string类型
        //第一步保存当前的方法
        var method=desc.value;
        //第二部修改当前的value
        desc.value=function(...args:any[]){
            //把接收到的参数改为string类型
            //循环遍历args这个数组,把数组里面的每一项转换为数组
            args=args.map((value)=>{
                return String(value)
            })
            console.log(args)
            method.apply(this,args)   //表示在这个方法里面,调用这个method,并且把这个args参数传入了

        }
    }
}
class http{
    url:any|undefined;
    constructor(){
    }
    @login("http://www.baidu.com")
    get(...args:any){
        console.log(args)
        console.log('我是get方法')
    }
}
var a:any=new http()
a.get(123,'***')

 方法参数装饰器

参数装饰器表达式会在运行时当做函数调用,可以使用参数装饰器为类的原型增加一些元素数据,传入3个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 参数的名字
  • 参数在函数参数列表中的索引
function login(params:any){
        return function(target:any,paramsName:any,paramsIndex:any){
            console.log(params)      //u
            console.log(target)       //当前类的原型对象
            console.log(paramsName)    //当前方法的名称
            console.log(paramsIndex)    //当前索引的位置

        }
}
class http{
    url:any|undefined;
    constructor(){
    }
    //在方法的参数里面调用与类以及属性,方法上是一样的
    get(@login('u')u:any){
        console.log(u)
        console.log('我是get方法')
    }
}
var a=new http();
a.get(123)

 

参数装饰器为类的原型增加一些元素数据

 

function login(params:any){
        return function(target:any,paramsName:any,paramsIndex:any){
            console.log(params)      //u
            console.log(target)       //当前类的原型对象
            console.log(paramsName)    //当前方法的名称
            console.log(paramsIndex)    //当前索引的位置
            //添加一个属性
            target.api=params
        }
}
class http{
    url:any|undefined;
    constructor(){
    }
    //在方法的参数里面调用与类以及属性,方法上是一样的
    get(@login('u')u:any){
        console.log(u)
        console.log('我是get方法')
    }
}
var a:any=new http();
a.get(123)
console.log(a.api)

 

posted @ 2021-11-06 17:52  keyeking  阅读(90)  评论(0编辑  收藏  举报