Search code examples
javascriptclassecmascript-6class-fields

JS Class Fields


With ES6 classes, we have getter and setter properties, but no field option (or at least that I know of).

With Object.defineProperty, you can set them with the value property. If at all, how do you do the same with classes?

I'm aware it can be done in the class constructor, but if possible I'd like for it to be separate.


Solution

  • You say above "they're the same thing regardless of language".

    Well, yes and no.

    Yes, there are obvious relations between programming languages, but Javascript/ECMAScript has some unusual features. Don't just come in expecting concepts to translate exactly.

    The key thing is that Javascript is not class-based, even though it does not have class-like syntax. It is prototype-based. This means you can declare any property on any object. You don't need to include it in a class declaration.

    For this reason, "class fields" were not included in the ES6 standard. It was expected that you would include them in the constructor method, as is normal in pre-ES6 Javascript.

    There is a proposal to create public class fields. These would look something like this:

    class Dog {
      constructor(name) {
        this.name = name;
      }
      bark() {
        console.log('woof');
      }
      tail = new Tail()
    }
    

    You could then have code that looked like this:

    let benji = new Dog('Benji');
    let rover = new Dog('Rover');
    console.log(benji.bark === rover.bark); // true
    console.log(benji.tail === rover.tail); // false
    

    The key thing is that every "instance" has the same method. However, each "instance" has a different property. This is the distinction that explains why this syntax was not originally included.

    As a proposal this is not currently supported. It can be used using transpilation, however. Babel.js (with, as I write, the Stage 2 preset transpiles the above code into this:

    class Dog {
      constructor(name) {
        this.tail = new Tail();
    
        this.name = name;
      }
      bark() {
        console.log('woof');
      }
    }