2

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.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Spedwards
  • 4,167
  • 16
  • 49
  • 106
  • I don't understand this question. Can you give an example of how "it can be done in the class constructor" so we can see what you are looking for? – lonesomeday Apr 04 '17 at 15:27
  • @lonesomeday In the class constructor, `this.whatever = 'someValue';` – Spedwards Apr 04 '17 at 15:54
  • 1
    So you mean object properties? "Class field" is not a concept that exists in JS. – lonesomeday Apr 04 '17 at 16:22
  • Yes... They're the same thing regardless of language. @lonesomeday – Spedwards Apr 04 '17 at 16:23
  • 1
    Initialisation of instance properties *should* be done in the constructor. What do you think is wrong with that? Why do you want to do it "separate"? – Bergi Apr 04 '17 at 17:12
  • @Bergi Extending a class. I don't want to create a new constructor in each extended class just to edit the instance properties. – Spedwards Apr 05 '17 at 11:27
  • @Spedwards Every class creates a new constructor anyway, and I don't see any reason why the three lines `constructor(...args) {`, `super(...args),` and `}` would hurt. – Bergi Apr 05 '17 at 16:10
  • @Bergi You don't need to create a constructor if you're extending one. I'd much rather 1 line than 4. – Spedwards Apr 05 '17 at 16:27

2 Answers2

6

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');
  }
}
lonesomeday
  • 233,373
  • 50
  • 316
  • 318
0

Class fields are now a stage 3 ECMAScript proposal and are already supported in current versions of Chrome and in Node.js 12. The proposal also references static fields.

class MyClass {
    static createdObjects = 0;
    objectNumber = MyClass.createdObjects++;
}
GOTO 0
  • 42,323
  • 22
  • 125
  • 158