TLDR, paste the following in your Chrome console:
class Animal {
#sound = 'rustling noise in the bushes'
get sound() { return this.#sound }
set sound(val) { this.#sound = val }
makeSound() {
console.log(this.#sound)
}
}
const a = new Animal
a.makeSound() // 3.14
class Lion extends Animal {
sound = 'RAWR!'
}
const lion = new Lion
lion.makeSound() // BUG! Expected "RAWR!" but got "rustling noise in the bushes"
The example does not work as you may expect because the expression sound = 'RAWR!'
uses [[Define]]
semantics instead of [[Set]]
semantics.
What are [[Define]]
and [[Set]]
semantics?
Let me explain using plain ES6 code without class fields.
Using [[Set]]
semantics, the Lion
class can be written like this:
class Lion extends Animal {
constructor() {
super()
this.sound = 'RAWR!'
}
}
That version will trigger super class getters/setters in the expression this.sound = 'RAWR!'
. The result of lion.makeSound()
will be "RAWR!"
because that value will be stored inside of the Animal
class's private #sound
field.
Now, using [[Define]]
semantics, we would instead "define" the property on the instance, like so:
class Lion extends Animal {
constructor() {
super()
Object.defineProperty(this, 'sound', { value: 'RAWR!' })
}
}
This version is what class fields do. Class fields define the property on this
directly, so the sound
field does not trigger the super class getter/setter that is inside of Animal, therefore the 'RAWR!'
value will never be stored inside of Animal's private #sound
field. Thus we've been shot in the foot.
Class fields do not keep inheritance as a first-class citizen in the design of JS class
es.
This is one of the reasons why many people don't like the class-fields proposal, and it is unfortunate that Chrome's V8 engine is already shipping the feature despite so much push-back from the community.
Here's the design bug reported to Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=962192
Ever since ES6 features started rolling out, there hasn't been any feature more controversial and disliked than the current class-fields proposal.
If you have any thoughts on (private or public) class-fields, please leave your thoughts over in those GitHub issues. The more community input we get, the better.
Top comments (0)