JS TS将装饰器应用于所有方法/枚举类方法 [英] JS TS apply decorator to all methods / enumerate class methods

查看:311
本文介绍了JS TS将装饰器应用于所有方法/枚举类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将装饰器函数应用于类中的所有方法,以便替换:

I would like to apply a decorator function to all methods within a class so I can replace:

class User {
    @log
    delete() {}

    @log
    create() {}

    @log
    update() {}
}

@log
class User {
    delete() {}
    create() {}
    update() {}
}


推荐答案

创建一个类装饰器并枚举属性

Create a class decorator and enumerate the properties on the target's prototype.

对于每个属性:


  1. 获取属性描述符。

  2. 确保它用于方法。

  3. 将描述符值包装在一个新函数中,该函数记录有关方法调用的信息。

  4. 将修改后的属性描述符重新定义为属性。

  1. Get the property descriptor.
  2. Ensure it's for a method.
  3. Wrap the descriptor value in a new function that logs the information about the method call.
  4. Redefine the modified property descriptor back to the property.

修改属性描述符非常重要,因为您要确保您的装饰

It's important to modify the property descriptor because you want to ensure your decorator will work well with other decorators that modify the property descriptor.

function log(target: Function) {
    for (const propertyName of Object.keys(target.prototype)) {
        const descriptor = Object.getOwnPropertyDescriptor(target.prototype, propertyName);
        const isMethod = descriptor.value instanceof Function;
        if (!isMethod)
            continue;

        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            console.log("The method args are: " + JSON.stringify(args));
            const result = originalMethod.apply(this, args);
            console.log("The return value is: " + result);
            return result;
        };

        Object.defineProperty(target.prototype, propertyName, descriptor);        
    }
}

基类方法

如果您希望它也影响基类方法,则可能需要遵循以下内容:

If you want this to affect the base class methods as well, then you might want something along these lines:

function log(target: Function) {
    for (const propertyName in target.prototype) {
        const propertyValue = target.prototype[propertyName];
        const isMethod = propertyValue instanceof Function;
        if (!isMethod)
            continue;

        const descriptor = getMethodDescriptor(propertyName);
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            console.log("The method args are: " + JSON.stringify(args));
            const result = originalMethod.apply(this, args);
            console.log("The return value is: " + result);
            return result;
        };

        Object.defineProperty(target.prototype, propertyName, descriptor);        
    }

    function getMethodDescriptor(propertyName: string): TypedPropertyDescriptor<any> {
        if (target.prototype.hasOwnProperty(propertyName))
            return Object.getOwnPropertyDescriptor(target.prototype, propertyName);

        // create a new property descriptor for the base class' method 
        return {
            configurable: true,
            enumerable: true,
            writable: true,
            value: target.prototype[propertyName]
        };
    }
}

这篇关于JS TS将装饰器应用于所有方法/枚举类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆