2

I was messing around with classes when I found this weird behaviour:

class A {
  test = 1
}

class B extends A {
  get test () {
    return 2
  }
}

const b = new B()

console.log(b.test)

The logical answer to the output should be 2 but when running the code, the output is 1.

Am I missing something? Is this intended javascript behaviour? I could not find anything in the MDN documentation about this.

I found this question which might be related to mine but it did not include any work arounds.

deceze
  • 510,633
  • 85
  • 743
  • 889
Dinhero21
  • 63
  • 4
  • 2
    `test = 1` is a field, i.e. a property on the _instance_. Getters will be placed on the prototype. Property access will check the instance (i.e. own properties) before the rest of the prototype chain. – Sebastian Simon Jan 13 '23 at 13:33
  • Related: https://stackoverflow.com/questions/68477998/how-to-properly-override-an-accessor-getter-in-the-prototype-of-a-base-class, https://stackoverflow.com/questions/69477028/is-it-valid-to-override-a-property-in-the-javascript-typescript-base-class-with – Bergi Jan 13 '23 at 14:57
  • Sorry for accidentally closing, it seems we have no proper canonical question for this. The closest would be https://stackoverflow.com/questions/50805007/class-method-doesnt-override-class-field, but that explains it for methods not for getters – Bergi Jan 13 '23 at 15:06

2 Answers2

1

You would have to redefine the value of test inside of B.

class A {
  test = 1
}

class B extends A {
  test = 2 // redefine
}

const b = new B()

console.log(b.test) // 2

If you check out MDN - References - JavaScript - Functions - getter, you will see that this is not possible.

Description


Note the following when working with the get syntax:

  • It must not appear with a data entry for the same property e.g. the following is forbidden
    {
      x: /* … */, get x() { /* … */ }
    }
    
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • I think the note in MDN only applies to a property `x` on the _same object_ that would act as both an accessor property and a data property. In OP’s example, both of these exist, but not on the same object. – Sebastian Simon Jan 13 '23 at 17:13
0

As pointed out by Mr. Polyshirl and Sebastian Simon, it is not possible to overwrite an inherited property using a getter. My "solution" was to use plain-old functions instead of getters and setters.

So, for example, instead of using

class Example {
  method = 'value'
}

const example = new Example()

console.log(example.method)

use

class Example {
  #method = 'value'

  getMethod () {
    return this.#method
 }

 setMethod (method) {
   this.#method = method

   // Use return this to allow for method chaining
   return this
 }
}

const example = new Example()

console.log(example.getMethod())

or

class Example {
  getMethod () {
    return 'value'
  }
}

const example = new Example()

console.log(example.getMethod())
Dinhero21
  • 63
  • 4
  • You could actually use a proper accessor (getter/setter) property, since it is possible to overwrite the inherited getter/setter. – Bergi Jan 21 '23 at 12:25