0

Please explain the difference between using a parent-child relationship using anonymous functions and using class functions? In case 1 everything works as expected. In case 2, codepen does not return any results.

//CASE 1
class Parent {
  constructor(name) {
    this.name = name;
  }

  exec() {
    console.log('name', this.name);
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }

  exec() {
    super.exec();
    console.log('age', this.age);
  }
}

const c = new Child('ChildName', 31);
c.exec();

//writes Childname + 31 (expected behaviour)

and

//CASE 2
class Parent {
  constructor(name) {
    this.name = name;
  }

  exec = () => {
    console.log('name', this.name);
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }

  exec = () => {
    super.exec();
    console.log('age', this.age);
  }
}

const c = new Child('ChildName', 31);
c.exec();

//writes nothing. Seems to crash.
Barmar
  • 596,455
  • 48
  • 393
  • 495
Recipe
  • 1,318
  • 3
  • 14
  • 27

1 Answers1

0

There is just one instance object, and there can't be two properties with the same name on one object. Your subclass property overrides the property of the superclass.

Additionally you can't access properties via super as super refers to the upper level prototype, and that does not contain any property in your second case (in your first case it contains the method). Therefore, super.exec is undefined, and calling that throws an error.

The prototype chains look as follows:

 // Case 1
                                              - super ------------v
 { name: "ChildName", age: 31 } -> Child { exec() { ... } } -> Parent { exec() { ... } }


 // Case 2
                                  - super² --------------------v                   
 { name: "ChildName", age: 31, exec() { ... } } -> Child {} -> Parent {}

² It might be a bit confusing that super inside of the instance points to Parent, but that's because class fields are evaluated inside of a special initializer function, and that has Child as it's [[HomeObject]], not the instance, and as super refers to the [[HomeObject]]s prototype, it will refer to Parent.

Jonas Wilms
  • 106,571
  • 13
  • 98
  • 120
  • Then why is CASE 1 working just fine? calling super methods works, but just not with anonymous functions. – Recipe Aug 19 '19 at 15:14
  • I'm not quite sure on my last statement, I'll reread the relevant spec sections, I'll be back soon – Jonas Wilms Aug 19 '19 at 15:31
  • Update: `super` is lexically resolved, just like `this`, so depending on how the closure gets created for class fields, this *could work*, `super.exec` will still be `undefined` then though. – Jonas Wilms Aug 19 '19 at 15:36
  • Update2: It does actually work. [According to the proposal](https://tc39.es/proposal-class-fields/#runtime-semantics-class-field-definition-evaluation) the initializer gets executed inside of a function that behaves exactly like the constructor(), so both `this`and `super` can be accessed. Won't work still. – Jonas Wilms Aug 19 '19 at 15:43