如何使用 JavaScript/TypeScript 在 class 代理处理程序中获取 属性 描述符

How do I obtain a property descriptor inside of a class proxy handler using JavaScript/TypeScript

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

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"

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

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

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)
    }
}

我认为没有从超级 class 拦截实例属性的实用方法,所以我放弃了。对于我的特定用例,足以防止首先通过 Object.freeze:

定义 public 属性
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"