【问题标题】:Create a class with getters based on the properties of another class根据另一个类的属性创建一个带有 getter 的类
【发布时间】:2021-05-14 09:22:56
【问题描述】:

假设我有一个具有一百个属性的 A 类:

class A {
  FOO = "foo";
  BAR = "bar";
  // (...) 98 more properties
}

在打字稿中,如何动态定义一个类 B,为类 A 的每个属性使用一个 getter?
对应的静态定义类 B 如下所示:

class B {
  get FOO() {
    someFunction('FOO');
  }

  get BAR() {
    someFunction('BAR');
  }

  // (...) 98 more getters
}

这些类之间的关系如下:

  • B 中的 getter 名称等于 A 中的属性名称
  • B 中 getter 的主体正是函数 someFunction 的调用,其单个参数是一个带有 getter 名称的字符串

【问题讨论】:

  • 这两个类有什么关系?
  • 感谢您的提问!我在问题中添加了更多信息。希望它能回答你的问题。

标签: javascript typescript


【解决方案1】:

一种选择是动态定义吸气剂:

class A {
    FOO = "foo";
    BAR = "bar";
    // (...) 98 more properties
}

function someFunction(p) {
    console.log('someFunction', p)
}

class B {
    constructor(a) {
        for (let p of Object.getOwnPropertyNames(a))
            Object.defineProperty(this, p, {
                get: () => someFunction(p) 
            })
    }
}

b = new B(new A)
b.FOO
b.BAR

我猜你也需要将a 传递给someFunc,否则它怎么知道从哪个对象中选择属性?

另一个是使用Proxy:

class A {
    FOO = "foo";
    BAR = "bar";
    // (...) 98 more properties
}

function someFunction(p) {
    console.log('someFunction', p)
}

class B {
    constructor() {
        return new Proxy({}, {
            get(target, p) {
                return p in target ? Reflect.get(target, p) : someFunction(p)
            }
        })
    }
}

b = new B()
b.FOO
b.BAR

在后一种情况下,B 和 A 实际上是独立的,因此 B 只是一个“空心”对象,它将所有内容重定向到 someFunc

【讨论】:

    【解决方案2】:

    这是@georg 的回答,第二个建议,稍作改动以实际为我工作:

    class A {
        FOO = "foo";
        BAR = "bar";
        // (...) 98 more properties
    }
    
    function someFunction(p, moreStuff) {
        console.log('someFunction', p, moreStuff)
    }
    
    class B extends A {
        constructor(private something: Something) {
            super();
            const someth = this.something;
            return new Proxy({} as any, {
                get(target, p) {
                    return p in target ? Reflect.get(target, p) : someFunction(p, someth)
                }
            })
        }
    }
    
    b = new B()
    b.FOO
    b.BAR
    

    【讨论】:

    • 这个答案和@georg给出的答案有什么区别?
    • 重要的区别在于 B 从 A 扩展而来,并且 Proxy 的第一个参数是 {} as any。如果没有这个,当我尝试从b 访问 FOO 时出现错误:b.FOO。然后有一个不相关的区别(与问题无关,因为我忘了提及),即构造函数有一个参数 something 最近在 someFunction 中使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-21
    相关资源
    最近更新 更多