dcangulo
dcangulo

Reputation: 2107

How to override class arrow function method

I know this is something simple but I can't seem to find an answer to my question.

Many references that if you have the same function name only the last instance of the function will be called when the function is called (override).

I can't seem to do this if the function is an arrow function.

Normal function behavior:

class A {
  constructor() {
    this.something();
  }

  something() {
    console.log('I am A');
  }
}

class B extends A {
  something() {
    console.log('I am B');
  }
}

let b = new B();

This does overrides the something() function in class A but I can't seem to override function something() if it is in an arrow function format.

class A {
  constructor() {
    this.something();
  }

  something = () => {
    console.log('I am A');
  }
}

class B extends A {
  something = () => {
    console.log('I am B');
  }
}

let b = new B();

Why is the output of the two are different? How can I override the arrow function in the parent class correctly?

Upvotes: 7

Views: 2771

Answers (2)

trincot
trincot

Reputation: 349843

The key issue here is that a public instance field is a property on the instance, not on the prototype.

Then by the sequence of execution, when the constructor of B is invoked, this first initialises the new object (this) by running the constructor of A. There, the property this.something is defined, and it is immediately called. At this moment the function that is a field in B is not yet defined on the instance. When the A constructor has completed, the B construction resumes, which defines this.something again, thereby overwriting the previous definition (which is forever lost), as it happens on the same this object and not on the prototype chain.

We could rewrite that code so it wouldn't use field syntax:

class A {
  constructor() {
    this.something = () => {
      console.log('I am A');
    }
    this.something();
  }
}

class B extends A {
  constructor() {
    super();
    this.something = () => {
      console.log('I am B');
    }
  }
}

let b = new B();

This is really doing the same thing, but from this code it may be easier to understand why it outputs "I am A".

This is in contrast to how methods work in a class: they are functions that are defined on the prototype object, even before any instance is created, and as A and B have their own, distinct prototype object, both versions of something will be available on the prototype chain, not as an own property on the instance itself. So if you call it (as a method) on this, the closest one on the prototype chain will be the one that is called.

Upvotes: 1

Matthew
Matthew

Reputation: 3234

class A {
  constructor() {
    this.something();
  }

  something = () => {
    console.log('I am A');
  }
}

class B extends A {
constructor() {
    super();
    this.something();
  }
  something = () => {
    console.log('I am B');
  }
}

let b = new B();

This works for me. What is happening is that you're calling this.something() inside of Class A, therefore it will use its own method in Class A. If you call this in class B, it will use it own constructor which overrides Class A constructor. You can also call Class A in Class B by using super.something();

Upvotes: 0

Related Questions