我正在尝试代理一个ES6构造函数(主要是尝试模拟Python的描述符来获得乐趣和学习):



class _Record {
    constructor(data) {
        this._data = data;
    }
}

const constrProxyHandlers = {
    construct: function(target, args, cstr) {
        let instProxyHandler = {
            get: (target, prop) => {
                if(prop in target._data) { return target._data[prop] }
                return target[prop]
            },
            set: (target, prop, val) => {
                if(prop in target._data) {
                    target._data[prop] = val;
                } else {
                    target[prop] = val;
                }
                return true
            }
        }

        let obj = Object.create(cstr.prototype)
        cstr.apply(obj, args)
        return new Proxy(obj, instProxyHandler)
    }
}

const Record = new Proxy(_Record, constrProxyHandlers)

let rec = new Record({name: 'Vic', age: 25})
console.log([rec.name, rec.age])
rec.name = 'Viktor'
console.log(rec)





如果运行此代码段,则会出现以下错误:

cstr.apply(obj, args)

TypeError: Class constructor _Record cannot be invoked without 'new'


如果我将cstr.apply替换为new cstr,则构造函数会很快耗尽堆栈(显然会进行无限递归)。

如果我用函数替换_Record类,则此方法有效(例如,可以通过Babel进行编译)。我可以使其与本机ES6一起使用吗?

谢谢。

P. S.如果有问题,我目前正在节点7.7.4上检查这些摘要。

最佳答案

那个部分

let obj = Object.create(cstr.prototype)
cstr.apply(obj, args)


不适用于ES6类。您需要使用

let obj = Reflect.construct(target, args, cstr);


(而不是您尝试执行的Reflect.construct(cstr, args)new cstr(...args),这实际上是无限递归的-IIRC target引用_Record,而cstr引用Record或其子类之一)。

09-18 01:06