I'm testing the following code in Chrome Canary 63 and on Chrome 61. The goal of the code is to set a method that calls super onto a class instance (z
). In my codebase sometimes property blocks are cloned with Object.assign before being added to the instance and whenever this happens the code fails.
I've reproduced the problem with the code example below. The code works fine if avoid the shallow clone (props = Object.assign({}, props);
) but if I add that line I get TypeError: (intermediate value).bar is not a function
.
I've tried doing Object.create(this, Object.getOwnPropertyDescriptors(props))
instead of Object.assign
but it results in the same error.
Is there any way to properly set super
on objects that have been cloned?
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());
Is there any way to properly set
super
on objects that have been cloned?
Nope. super
uses the function's [[HomeObject]]
slot, which is set when the function (method) is created and cannot be changed at present.
Probably the best quote from the spec on this is in Table 27:
[[HomeObject]]
: If the function usessuper
, this is the object whose [[GetPrototypeOf]] provides the object wheresuper
property lookups begin.
The only thing you could do is try to change the prototype of the object that the function's [[HomeObject]]
refers to, but that A) Gets ugly fast, and B) Kills performance (in those situations where it matters).
If you're doing lots of "method" cloning, you're better off using simple properties that refer to functions, not methods, and not using super
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With