装饰器的详细介绍-访问器装饰器和属性装饰器

113 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

属性访问器基本使用

属性访问器有get和set,读取属性时执行get方法,设置属性时执行set方法,下面代码执行console.log(p.name) 时,直接执行了get 方法,打印了get,执行p.name='骚帮'时,直接执行了set方法,打印了set 骚帮。

class Person {
    _name: string
    constructor(name) {
        this._name = name;
    }
    get name() {
        console.log('get')
        return this._name;
    }
    set name(name: string) {
        console.log('set', name)
        this._name = name;
    }
}
let p = new Person('实则棒');
console.log(p.name)
p.name = '骚帮'

和普通的方法表现一致,访问器的装饰器第一个参数也是类的原型对象,console.log(target===Person.prototype)的值为true, 然后将descriptor.writable改为false,再修改name属性就直接报错了,因为这个值设置了不可写


function testDecorator(target, key, descriptor) {
    console.log(target===Person.prototype)
    console.log(target, key, descriptor)
    descriptor.writable=false
}



class Person {
    _name: string
    constructor(name) {
        this._name = name;
    }
    @testDecorator
    get name() {
        console.log('get')
        return this._name;
    }
    set name(name: string) {
        console.log('set', name)
        this._name = name;
    }
}
let p = new Person('实则棒');
console.log(p.name)
p.name = '骚帮'

属性装饰器

属性装饰器,只能接收两个参数,和方法装饰器仅仅就差了属性描述配置参数。他的第一个参数target也是类的原型对象,第二个参数也是一个字符串,属性名。

function testDecorator(target, key) {
    console.log(target === Person.prototype)
    console.log(target, key)
}



class Person {
    @testDecorator
    name = '骚帮'
}
let p = new Person();
console.log(p.name)

虽然属性装饰器没有第三个参数,但是属性装饰器也可以将属性设置成不可写属性,属性装饰器可以返回一个对象,这个对象会被当作属性的描述对象。如果设置了writable为false,那么这个属性就不可以被修改了



function testDecorator(target, key):any {
    console.log(target === Person.prototype)
    console.log(target, key)
    const descriptor:PropertyDescriptor={
        writable:false
    }
    return descriptor
}



class Person {
    @testDecorator
    name = '骚帮'
}
let p = new Person();
console.log(p.name)

这个例子没什么好说的,因为target 是Person的原型对象,所以给target加个key属性,就直接加到了原型对象上




function testDecorator(target, key):any {
    console.log(target === Person.prototype)
    target[key]='实则棒'
}



class Person {
    @testDecorator
    name = '骚帮'
}
let p = new Person();
console.log(p.name)
console.log(Person.prototype.name)