3

can someone explain the following to me?

class BaseClass {
  prop = 88;
  constructor(){
    console.log("baseClass prop is ", this.prop);
  }
}
class DerivedClass extends BaseClass{
  prop = 83;
  constructor(){
    super();
    console.log("derivedClass prop is ", this.prop);
  }
}
new derivedClass();

and the output is

baseClass prop is  88
derivedClass prop is  83

now shouldn't both props be the same (83)? because one prop overridden the other? Am i getting something wrong here?

3 Answers3

4

You are forgetting about the super() call in the constructor of your derived class.

What this does is call the constructor of the base class. So the constructor of the base class is run to completion prior to the constructor of the derived class.

Meaning when the console.log statement of the base class is executed, the prop variable is still 88.

shotor
  • 763
  • 6
  • 17
2

Class properties are initialized on construction from the bottom of the class heirarchy up, as the constructors are executed.

  • On base classes, they initialized inside the constructor automatically at the start.
  • On subclasses, they run immediately after super().

The logic is essentially

this.prop = 88;
console.log("baseClass prop is ", this.prop);

this.prop = 83;
console.log("derivedClass prop is ", this.prop);

because the class are

class BaseClass {
  constructor(){
    this.prop = 88;
    console.log("baseClass prop is ", this.prop);
  }
}

class DerivedClass extends BaseClass {
  constructor(){
    super();
    this.prop = 83;
    console.log("derivedClass prop is ", this.prop);
  }
}
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
0

Your code is invalid. ES6 is not TypeScript, so your class attributes must be declared inside your constructors. Moreover, you should follow a coding convention that favors pascal case over camel case for class names. Here is the correct syntax:

class BaseClass {
  constructor(){
    this.prop = 88;
    console.log("BaseClass prop is", this.prop);
  }
}
    
class DerivedClass extends BaseClass {
  constructor(){
    super();
    this.prop = 83;
    console.log("DerivedClass prop is", this.prop);
  }
}
    
new DerivedClass();

So, why do we have 88 and 83? In fact, when your derived class calls the base class via super(), this.prop is 88 and you log it immediately. When super() execution ends, this.prop becomes 83, but there is no reason for your previous log to disappear...

Now, if you want private attributes for some reasons, you could declare them outside your constructors, but you would need IIFEs (Immediately-Invoked Function Expressions):

const BaseClass = (() => {
  let prop = 88;

  class BaseClass {
    constructor(){
      console.log("BaseClass prop is", prop);
    }
  }

  return BaseClass;
})();
 
const DerivedClass = (() => {
  let prop = 83;
    
  class DerivedClass extends BaseClass {
    constructor(){
      super();
      console.log("DerivedClass prop is", prop);
    }
  }
  
  return DerivedClass;
})();
    
new DerivedClass();

As you can see, each class uses the prop variable defined in its own scope.

Badacadabra
  • 8,043
  • 7
  • 28
  • 49
  • Presumably the OP is using the *public class field* experimental feature, but you are right, it's not valid JS at the moment. – Felix Kling Apr 28 '17 at 18:33
  • Yeah actually I was using babel, so I don't look at the compiled javascript. So I never know what the the public class field actually compiles to. Maybe I shouldn't use experimental features without knowing how they work lol :) Thanks for taking the time to answer my question. – Mohamed Abo El Soud Apr 28 '17 at 23:48
  • and btw I do use pascal case for my naming convention, I just wanted to whip up a simple example that I could post on StackOverflow. I don't actually use "baseClass" in my code lol :) – Mohamed Abo El Soud Apr 28 '17 at 23:52
  • It's good to know that camel case is a reflex for you. Still better than snake case... ^^ – Badacadabra Apr 28 '17 at 23:57