Reputation: 35
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
Why is assigning a value to super in the constructor in the ES6 standard? It is assigning a value to an instance of the class.
Why is super.x
undefined
while this.x
is 3
Upvotes: -1
Views: 75
Reputation: 23309
What happens
this
(which is an instance of the class used with new
), so assigning this.x = 1
in a super's constructor and in the child constructor are the same.super.x = 3
. a x
's SETTER is looked up in the prototype chain starting from super
(A.prototype
) and when not found, x
is assigned to this
. But when reading super.x
, a x
's GETTER is looked up from super
and when no found there's no fallback for this
so undefined
is returned 🤷♂️.How to solve (to have (kind of?) multiple same name property per a class in an instance (if needed))
super
for x you should DEFINE the B class with x
property, otherwise this.x = 2
in the B's constructor will use the setter and won't assign x
to this
but rather to this.#x
in the super.class A {
#x;
constructor() {
this.#x = 1;
}
get x(){ return this.#x }
set x(v){ this.#x = v }
}
class B extends A {
x; // this is required to ensure this.x = 2 to work
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
You can also use symbols:
const propX = Symbol('propX');
class A {
constructor() {
this[propX] = 1;
}
get x(){ return this[propX] }
set x(v){ this[propX] = v }
}
class B extends A {
x; // this is required to ensure this.x = 2 to work
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
With symbols you could create some generic solution:
class A {}
createClassProp(A, 'x', 1);
class B extends A {
x; // this is required to ensure this.x = 2 to work
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
console.log(new A().x);
<script>
function createClassProp(target, name, initVal){
const symbol = Symbol(name);
Object.defineProperty(target.prototype, name, {
enumerable: false,
get(){
if(Object.hasOwn(this, symbol)) return this[symbol];
return Object.hasOwn(this, name) ? this[name] : initVal;
},
set(v){
this[symbol] = v;
}
});
}
</script>
Upvotes: 1