【问题标题】:Typescript: Calling Method from within Method Parameters打字稿:从方法参数中调用方法
【发布时间】:2016-10-26 01:33:19
【问题描述】:

我想这更像是一个好奇的问题,如果它真的可以在 typescript 中实现就好了。

基本上我有一个类和两个方法,如下所示:

这可能吗?


class MyClass{
   private cleanup(str:String):String{
     //clean up the string
     return str; //return sanitized string
   }
   //I want to do this
   insertString(this.cleanup(text_1:String), this.cleanup(text_2:String)){
     console.log(text_1 + text_2);
   }
}

而不是这个?


class MyClass{
   private cleanup(str:String):String{
     //clean up the string
     return str; //return sanitized string
   }
   //might get to long if I have to cleanup to many strings
   insertString(text_1:String, text_2:String){
     text_1 = this.cleanup(text_1)
     text_2 = this.cleanup(text_2)
     console.log(text_1 + text_2);
   }
}

【问题讨论】:

  • 这个insertString(this.cleanup(text_1:String), this.cleanup(text_2:String))不是函数声明,所以不可能。函数声明包含参数的数量及其类型。如果你想对参数做一些事情,它必须在函数体中完成。
  • @Tomalak 甚至不使用 insertString(text_1:String = this.cleanup(text_1), text_2:String = this.cleanup(text_2)) 之类的东西或某种类似箭头函数的语法?

标签: javascript class methods typescript


【解决方案1】:

您要实现的实际上并不是从另一个方法签名中调用方法。更多的是处理您的参数列表。

1:arguments黑客

您可以修改提供的arguments数组,相应的命名参数也会发生变化。

insertString(text_1:String, text_2:String) {
    // here text_1 and text_2 are not cleaned up yet
    for (var i = 0; i < arguments.length; i++) {
        arguments[i] = this.cleanup(arguments[i])
    }
    // text_1 and text_2 are now cleaned up
}

但是,这种方法很老套,您可以使用 #2:

2:装饰器

我们声明了两个装饰器:一个名为cleanup参数装饰器:

function cleanup(target: Object, propertyKey: string | symbol, parameterIndex: number) {
    let cleanupParams: number[] = Reflect.getOwnMetadata("MyClass:cleanup", target, propertyKey) || [];
    cleanupParams.push(parameterIndex);
    Reflect.defineMetadata("MyClass:cleanup", cleanupParams, target, propertyKey);
}

还有一个名为CleanupMethod方法装饰器(它实际上是一个装饰器工厂):

function CleanupMethod(func){
    return function (target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
        let method = descriptor.value;
        descriptor.value = function () {
            let requiredParameters: number[] = Reflect.getOwnMetadata("MyClass:cleanup", target, propertyName);
            if (requiredParameters) {
                for (let parameterIndex of requiredParameters) {
                    arguments[parameterIndex] = func(arguments[parameterIndex]);
                }
            }
            return method.apply(this, arguments);
        }
    }
}

在装饰器中,我们保存了一个列表,其中列出了应该在函数输入时对哪些参数进行清理,然后在每次调用时对它们进行清理。

用法:

class MyClass{
    private cleanup(str:string):string{
        //clean up the string
        return '[sanitized ' + str + ']'; //return sanitized string
    }
    @CleanupMethod(MyClass.prototype.cleanup)
    insertString(text_1:string, @cleanup text_2:string){
        console.log(text_1 + text_2);
    }
    @CleanupMethod(MyClass.prototype.cleanup)
    insertNumber(n1: number, n2: number, @cleanup n3: number, n4: number, n5: number){
        console.log(`${n1} + ${n2} + ${n3} + ${n4} + ${n5}`)
    }
}
var m = new MyClass();
m.insertString('a', 'b') // outputs `a[sanitized b]`
m.insertNumber(10,20,30,40,50) // outputs `10 + 20 + [sanitized 30] + 40 + 50`

清理函数作为参数传递给CleanupMethod 工厂。这样你就可以有不同的清理功能,例如:

@CleanupMethod(cleanupString)
insertString( @cleanup str1: string, @cleanup str2: string2 ){
    /*...*/
}
@CleanupMethod(cleanupNumber)
insertNumber( @cleanup n1: number ){
    /*...*/
}

如果你愿意,你可以重写装饰器代码并将清理功能移动到参数装饰器,但这会增加所需的代码量:

@CleanupMethod
insertString( @cleanup(cleanupString) str1: string, @cleanup(cleanupNumber) n1: number ){
    /*...*/
}

More on decorators

【讨论】:

  • 很好的答案!这超出了我打算做的范围,但它仍然很有帮助且很有见地。
猜你喜欢
  • 2016-02-18
  • 1970-01-01
  • 2017-02-25
  • 2018-05-25
  • 2023-02-10
  • 2021-09-10
  • 1970-01-01
  • 2018-01-26
  • 2022-11-03
相关资源
最近更新 更多