js以编程方式应用装饰器

时间:2017-12-10 16:54:33

标签: javascript typescript decorator

我有一个类装饰器,并希望使用它将另一个装饰器应用于类中的所有方法,但我不太确定如何在没有@语法的情况下以编程方式应用装饰器:

@LogAllMethods
class User {
    greet() {
        console.log('Hello')
    }
}

function LogAllMethods(target) {
    for (const key in Object.keys(target.prototype)) {
        // apply LogMethod decorator
    }
}

function LogMethod(target, key, descriptor) {
    let method = descriptor.value
    decriptor.value = function(...args) {
        console.log(args)
        method.apply(this, ...args)
    }
}

1 个答案:

答案 0 :(得分:1)

你基本上只需要用目标,键(方法名称)和定义的描述符调用装饰器函数:

function LogAllMethods<T>(target: new (...params: any[]) => T) {
    for (const key of Object.getOwnPropertyNames(target.prototype)) {
        let descriptor = Object.getOwnPropertyDescriptor(target.prototype, key);
        descriptor = LogMethod(target.prototype, key, descriptor);
        if (descriptor) {
            Object.defineProperty(target.prototype, key, descriptor);
        }
    }
}

function LogMethod(target: any, key: symbol | string, descriptor: TypedPropertyDescriptor<any> = undefined) {

    if (descriptor) {
        let method = descriptor.value;
        if (method instanceof Function) {
            descriptor.value = function (...args: any[]) {
                console.log("Log", args)
                method.apply(this, ...args);
            }
        }
        return descriptor;
    } else {
        // descriptor is null for target es5 if the decorator is applied directly to the merhod
        let method = target[key];
        if (method instanceof Function) {
            target[key] = function (...args: any[]) {
                console.log("Log", args)
                method.apply(this, ...args);
            }
        }
    }
}