Setting properties of super
, such as super.x = 1
, behaves like Reflect.set(Object.getPrototypeOf(objectLiteral), "x", 1, this)
. This is one of the cases where understanding super
as simply "reference of the prototype object" falls short, because it actually sets the property on this
instead.
class A {}
class B extends A {
setX() {
super.x = 1;
}
}
const b = new B();
b.setX();
console.log(b);
console.log(Object.hasOwn(b, "x"));
super.x = 1
will look for the property descriptor of x
on A.prototype
(and invoke the setters defined there), but the this
value will be set to this
, which is b
in this context. You can read Reflect.set
for more details on the case when target
and receiver
differ.
This means that while methods that get super.prop
are usually not susceptible to changes in the this
context, those that set super.prop
are.
const b2 = new B();
b2.setX.call(null);
However, super.x = 1
still consults the property descriptor of the prototype object, which means you cannot rewrite non-writable properties, and setters will be invoked.
class X {
constructor() {
Object.defineProperty(this, "prop", {
configurable: true,
writable: false,
value: 1,
});
}
}
class Y extends X {
constructor() {
super();
}
foo() {
super.prop = 2;
}
}
const y = new Y();
y.foo();
console.log(y.prop);