初始class
class Greeter {
greeting: string;
greetTimes: number;
constructor(message: string) {
this.greeting = message;
this.greetTimes = 0;
}
greet() {
this.greetTimes += 1;
return `Hello, ${this.greeting}`;
}
}
decorator1
function decorateStr(deco = '') {
return (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
): TypedPropertyDescriptor<() => string> => {
function newVal(this: Greeter, ...params: Parameters<Greeter['greet']>) {
if (descriptor.value) {
return descriptor.value.call(this, ...params) + deco;
}
return descriptor.value.call(this, ...params);
}
return {
...descriptor,
value: newVal,
};
};
}
decorator2
function decorateWithGreetTimes(deco = '') {
return (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
): TypedPropertyDescriptor<() => string> => {
// this要加在這才行
function newVal(
this: Greeter,
...params: Parameters<Greeter['greet']>
) {
if (descriptor.value) {
return `${
descriptor.value.call(this, ...params) + deco
}--打招呼次數: ${this.greetTimes}次`;
}
return descriptor.value.call(this, ...params);
}
return {
...descriptor,
value: newVal,
};
};
}
結果
decorator1
//..
@decorateStr('hooo')
greet() { //... }
const greeter = new Greeter('say hi :)');
console.log(greeter.greet()); // say hi :)hooo
decorator2
//..
@decorateWithGreetTimes()
greet() { //... }
const greeter = new Greeter('say hi :)');
console.log(greeter.greet()); // say hi :)--打招呼次數: 1次
複合使用
@decorateStr('hiiii') // 這個decorator會在最後才呼叫,有點像是decorateStr('hiiii')(decorateWithGreetTimes()({ descriptor: { value: greet }}))這樣的函式呼叫法
@decorateWithGreetTimes()
greet() { //... }
const greeter = new Greeter('say hi :)');
console.log(greeter.greet()); // Hello, say hi :)--打招呼次數: 1次hiiii