es6类装饰器,如何能一次性修饰类下所有方法

如题:es6类装饰器,如何能一次性修饰类下所有方法。
如:将类下所有的方法执行前加入console.log

const log = (num) {
  console.log(num)
}
@log(1)
class demo {
  func() {
    console.log(2)   
  }
}
阅读 1.9k
3 个回答
function test(num: number) {
    return function(target: any, key: string, des: any) {
        //console.log(target);
        const d = Object.getOwnPropertyNames(target.prototype);
        for(const i of d) {
            if (i == 'constructor' ) {
                continue;
            }
            const old = target.prototype[i];
            target.prototype[i] = function(...args: any[]) {
                console.log(num);
                old(...args);
            }
        }
    }
}

@test(2)
class Test {
    say() {
        console.log('say');
    }
    say2() {
        console.log('say2');
    }
}

const t = new Test();
t.say();
t.say2();

类似这样试试?

根据TS目前的实现编写

function log(num) {
    return function decorator(klass) {
        class DecoratedClass extends klass { };
        Object.getOwnPropertyNames(klass.prototype).forEach(method => {
            if (method !== 'constructor' && typeof klass.prototype[method] === 'function') {
                DecoratedClass.prototype[method] = function (...args) {
                    console.log(num);
                    klass.prototype[method].apply(this,args);
                }
            }
        });
        return DecoratedClass;
    }
}

@log(1)
class Demo {
    func() {
        console.log(2)
    }
}

new Demo().func()

是想要这个效果吗?
playground
说实话在最终定稿前(很可能很长时间内都不会定稿)研究这些感觉没啥用,TS的实现是很旧的版本,babel上的current proposal似乎也不是最新的版本,可能过两天设计就变了也不是不可能

type PropertyDescriptorPair = [string | symbol, PropertyDescriptor];

function beforeAllMethods(fn: (key: string | symbol) => void) {
    return function (constructor: new (...args: any) => unknown) {
        const proto = constructor.prototype;
        Reflect.ownKeys(proto)
            .filter(key => key !== "constructor")
            .map(key => [key, Reflect.getOwnPropertyDescriptor(proto, key)] as PropertyDescriptorPair)
            .filter(([, { value }]) => typeof value === "function")
            .forEach(([key, descriptor]) => {
                const oldValue = descriptor.value;
                descriptor.value = function (...args: any[]) {
                    fn(key);
                    Reflect.apply(oldValue, this, args);
                };
                Reflect.defineProperty(proto, key, descriptor);
            });
    };
}

@beforeAllMethods((key) => console.log(`[Log] before calling ${String(key)}`))
class SomePerson {
    name: string = "Anonymouse";

    constructor(name?: string) {
        this.name = name ?? this.name;
    }

    greet() {
        console.log(`Hello ${this.name}`);
    }

    doSomething() {
        console.log(`${this.name} is doing something`);
    }
}

const p = new SomePerson("James");
p.greet();
p.doSomething();

// [Log] before calling greet
// Hello James
// [Log] before calling doSomething
// James is doing something
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题