使用调用super的方法分配浅克隆对象时的TypeError

Jar*_*rym 5 javascript ecmascript-6

我正在Chrome Canary 63和Chrome 61上测试以下代码.代码的目标是设置一个调用super到类实例(z)的方法.在我的代码库中,有时会在添加到实例之前使用Object.assign克隆属性块,并且只要发生这种情况,代码就会失败.

我用下面的代码示例重现了这个问题.如果避免浅克隆(props = Object.assign({}, props);),代码工作正常,但如果我添加该行,我得到TypeError: (intermediate value).bar is not a function.

我试过做Object.create(this, Object.getOwnPropertyDescriptors(props))而不是Object.assign但它会导致同样的错误.

有没有办法正确设置super已克隆的对象?

let Moo = class {
    bar() {
        return " [bar on Moo] ";
    }
};

let Zoo = class extends Moo { 
    bar() { 
        return " [bar on Zoo] " + super.bar();
    }
};

function addProps(inst, props) {
    // Code works if the line below is commented out but otherwise
    // results in TypeError: (intermediate value).bar is not a function
    props = Object.assign({}, props); // <-- Offending code

    Object.setPrototypeOf(props, inst.__proto__);
    Object.assign(inst, props);
}

let props = {
    onZooInst: {
        bar() {
            return " [bar on overridden instance] " + super.bar();
        }
    }
};

let z = new Zoo();
addProps(z, props.onZooInst);
console.log(z.bar());
Run Code Online (Sandbox Code Playgroud)

Jar*_*rym 0

对于任何可能面临同样问题的人,我终于找到了解决方案。

而不是像这样定义对象文字块

let a = {
    someFunc() {
        super.someFunc();
    } 
}
Run Code Online (Sandbox Code Playgroud)

您可以将它们替换为返回它们的箭头函数:

let a = () => {
    return {
        someFunc() {
            super.someFunc();
        } 
    }
};
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为a().someFunc !== a().someFunc- 换句话说,你得到一个新函数,我们不需要解析动态代码生成(eval/new Function)。您应该能够安全地Object.setPrototypeOf对 的返回值执行操作a()