我正在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());
答案 0 :(得分:3)
有没有办法在已克隆的对象上正确设置
super
?
不。 super
使用函数的[[HomeObject]]
插槽,该插槽在创建函数(方法)时设置,目前无法更改。
关于此规范的最佳引用可能是Table 27:
[[HomeObject]]
:如果函数使用super
,则[[GetPrototypeOf]]提供super
属性查找开始的对象的对象。
你唯一能做的就是尝试改变函数[[HomeObject]]
引用的对象的原型,但是A)变得丑陋 快 ,和B)杀死表现(在重要的情况下)。
如果您正在做很多&#34;方法&#34;克隆,您最好使用引用函数的简单属性,而不是方法,而不是使用super
。
答案 1 :(得分:0)
如果正确解释要求,您可以将props
对象的this.bar()
功能调整为Function.prototype.call()
并使用Function.prototype.apply()
,Reflect.apply()
或this
进行设置对props.onZooInst.bar
Moo.prototype
let Moo = class {
bar() {
return " [bar on Moo] ";
}
};
let Zoo = class extends Moo {
bar() {
return " [bar on Zoo] " + super.bar();
}
};
let props = {
onZooInst: {
bar() {
return " [bar on overridden instance] " + this.bar();
}
}
};
let z = new Zoo();
let reflectBar = Reflect.apply(props.onZooInst.bar, z.__proto__, []);
let callBar = props.onZooInst.bar.call(z.__proto__);
console.log(reflectBar);
console.log(callBar);
函数调用Properties
Description
&#13;
答案 2 :(得分:0)
对于任何可能遇到同样问题的人,我终于找到了解决方案。
而不是像
那样定义对象文字的块let a = {
someFunc() {
super.someFunc();
}
}
您可以使用返回它们的箭头函数替换它们:
let a = () => {
return {
someFunc() {
super.someFunc();
}
}
};
这是有效的,因为a().someFunc !== a().someFunc
- 换句话说,你得到了一个新功能,而我们不需要解决动态代码生成(eval / new Function)。您应该能够安全地对Object.setPrototypeOf
的返回值a()
执行。