首页 > 解决方案 > 如何使用 JavaScript/TypeScript 在类代理处理程序中获取属性描述符

问题描述

使用类代理,我想在执行特定操作之前询问属性描述符;如果它是访问器,则做一件事,如果它是方法,则做另一件事,如果它是属性,则做第三件事。但问题是我不认为我正在寻找该功能的正确所有者:

type Constructor<T> = new (...args: any[]) => T

const handler: ProxyHandler<any> = {
    get(target, propertyKey, receiver) {
        const desc = Object.getOwnPropertyDescriptor(target, propertyKey)
        console.log(desc) // undefined

        return Reflect.get(target, propertyKey, receiver)
    }
}

function Adapted<U extends Constructor<any> = Constructor<any>>(Base: U = Object as any) {
    return class extends Base {
        constructor(...args: any[]) {
            super(...args)

            return new Proxy(this, handler)
        }
    }
}

class Foo extends Adapted() {
    method() { return "foo" }
}

new Foo().method() // "foo"

我必须走原型链直到找到正确的所有者吗?是不是更简单一些?

标签: javascripttypescriptreflection

解决方案


评估直接原型似乎就足够了。谢天谢地,不必走原型链:

const handler: ProxyHandler<any> = {
    get(target, propertyKey, receiver) {
        const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(target), propertyKey)

        // do something based on desc type

        return Reflect.get(target, propertyKey, receiver)
    }
}

我不认为有一种实用的方法可以从超类中截取实例属性,所以我已经放弃了。对于我的特定用例,首先防止通过以下方式定义公共属性就足够了Object.freeze

function Adapted<U extends Constructor<any> = Constructor<any>>(Base: U = Object as any) {
    return class extends Base {
        constructor(...args: any[]) {
            super(...args)

            return Object.freeze(new Proxy(this, handler))
        }
    }
}

仍然允许实际使用:

class Foo extends Adapted() {
    #prop: string
    constructor(prop: string) {
        super()
        this.#prop = prop
    }

    get prop(): string {
        return this.#prop
    }
    set prop(value: string) {
        this.#prop = value
    }

    method() { return "method" }
}

class Bar extends Foo {
    method2(){ return "method2" }
}

let foo = new Foo("prop1"),
    bar = new Bar("prop2");

console.log(foo.prop) // prop1
console.log(bar.prop) // prop2

bar.prop = "12"

console.log(bar.prop) // "12"

推荐阅读