9

Is there a JavaScript syntax that lets me do the following more succinctly?

class MyClass {
    static get myProp() {
        return 1;
    }
}

It is not a huge deal, but I'd like to know if there was something that was like an arrow function that lets me make it just a little more streamlined, something like:

class MyClass {
    static get myProp = () => 1;
}

I know I could write it like this (though not a safe equivalent):

class MyClass {}
MyClass.myProp = 1;

Or this more-difficult-to-read and longer alternative:

class MyClass {}
Object.define(MyClass, 'myProp', { get: () => 1; });

But that feels like an abuse of the class syntax.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
samanime
  • 25,408
  • 15
  • 90
  • 139
  • See also http://stackoverflow.com/questions/31362292/how-to-use-es6-arrow-in-class-methods - it seems 'arrow methods' are (still?) an experimental ES7 feature – le_m May 15 '17 at 16:12
  • 1
    Most times when people do `static get myProp() { ...` they don't really need read-only property. It's just idiomatic way to lift `MyClass.myProp = 1` above `constructor` (e.g. useful for AngularJS $inject annotations). There's no alternative except the ones you've listed. `static get myProp = () => 1` is obviously not supported because there's no reason to let it be assigned to anything but function. – Estus Flask May 15 '17 at 16:25
  • 2
    What do you mean by "*though not a safe equivalent*"? – Bergi May 15 '17 at 17:07
  • @le_m: If it's experimental then it's not ES7. ES7 (ES2016) was released last year. – Felix Kling May 15 '17 at 17:17
  • @FelixKling You are right. I wrote that after reading an old comment of yours "[...] this is an experimental feature for a ES7 proposal." – Felix Kling Jul 11 '15 at 22:23. I should have used past tense. Do you know whether it is still on track to become part of the standard in the future? – le_m May 15 '17 at 17:19
  • 1
    @le_m: Yep, still on track, currently in stage 2: https://github.com/tc39/proposals (Public Class Fields) :) It may or may not get into the spec next year (kinda impossible to know with these proposals). – Felix Kling May 15 '17 at 17:24
  • @Bergi A real getter is read-only, `MyClass.myProp = 1` is mutable. – samanime May 15 '17 at 20:23
  • 1
    @samanime I could also overwrite the "real getter" if I wanted to, though not with simple assignment. But really, since there is no dynamic computation of the value, you should not use a getter at all - regardless whether with or without arrow functions. – Bergi May 15 '17 at 20:26
  • @Bergi I don't necessarily disagree, but since JavaScript offers no way (at least that I know of) to define a class constant (in a class constant syntax), using a getter is arguably the cleanest method. Additionally, in my particular case, I'm actually returning an object (which could be internally mutable), so returning a new instance of the object is a good idea. – samanime May 15 '17 at 20:48
  • Would a custom class constructor be an alternative? – Jonas Wilms Dec 09 '17 at 21:07

2 Answers2

3

There is a better way to do it. It can be done using Babel Preset for class-transform. The preset to get this particular feature is 'preset-stage-2'.

The documentation page of babel for preset-stage-2: https://babeljs.io/docs/plugins/preset-stage-2/

Use Case: In your .bablerc file ad the present.

{
  "presets": ["stage-2"]
}

Note: it is a separate npm module so install it beforehand.

Bharat23
  • 527
  • 3
  • 15
  • This is the correct way. This was a question I asked a while back, and we've actually been using this for several months now, though we just use `transform-class-properties` as a plugin without the presets, same thing. – samanime Dec 11 '17 at 11:47
1

You can't use arrow functions to define class functions within a class declaration. Attempting to do so generates a syntax error.

The following code:

class MyClass {
  static get myVal() {
    console.log(this);
    return 1;
  }

  static get yourVal = () => {
    console.log(this);
    return 2;
  }
}

Produces this error:

{
  "message": "Uncaught SyntaxError: Unexpected token =",
  "filename": "https://stacksnippets.net/js",
  "lineno": 19,
  "colno": 22
}

And this code:

class MyClass {
  dogs = (val) => {
   console.log('Bark, bark', val);
  }
}

produces this error:

{
  "message": "Uncaught SyntaxError: Unexpected token =",
  "filename": "https://stacksnippets.net/js",
  "lineno": 14,
  "colno": 12
}

This code:

class MyClass {}
Object.define(MyClass, 'myProp', { get: () => 1; });

Is just the ES5 version to this code:

class MyClass {
  static get myProp() { return 1; }
}

This code:

class MyClass {}
MyClass.myProp = 1;

Is does attach myProp to the prototype of the class and is the equivalent of a static variable. But that value can be changed. So if you want a read only property then you need one of the above setters..

In this code:

class MyClass {
  static get myVal() {
    return 1;
  }
}
MyClass.yourVal = 33;

console.log(MyClass.myVal);
console.log(MyClass.yourVal);

We get the output of 1 and 33. Which is what was expected

Intervalia
  • 10,248
  • 2
  • 30
  • 60
  • One of the newer syntaxes allows arrow functions in classes, you just have to use a babel transform to do it. – samanime Dec 11 '17 at 15:29
  • You said nothing of using Babel in your question. I was stating the rules of ES6. If Babel breaks those rules then it sounds like Babel is broken. I would appreciate your not marking my answer down since my answer conforms with real ES6 rules – Intervalia Dec 11 '17 at 15:34
  • While it isn't accepted yet, it is an official proposal that is on track for being accepted (stage 3 of 4): https://github.com/tc39/proposal-class-fields. I didn't explicitly specify an ES-level, I just asked for a syntax. – samanime Dec 11 '17 at 15:43
  • You used the tag [tag:ecmascript-6] – Intervalia Dec 11 '17 at 15:47