Gabor Dolla
Gabor Dolla

Reputation: 2736

ES6 getter/setter with arrow function

I'm using babel6 and for my pet project I'm creating a wrapper for XMLHttpRequest, for the methods I can use:

open = (method, url, something) => {
  return this.xhr.open(method, url, something);
}

but for the properties arrow function doesn't work

this works:

get status() { return this.xhr.status; }

but I can not use

get status = () => this.xhr.status;

Is this intentional?

Upvotes: 182

Views: 61898

Answers (3)

hossein sedighian
hossein sedighian

Reputation: 2035

        _getvalue: () => {
            return this.array.length;
        }
        get value(): number {
            return this._getvalue();;
        }

this solved my problem when I forced to use arrow function

Upvotes: -7

Nate Anderson
Nate Anderson

Reputation: 21074

The accepted answer is great. It's the best if you're willing to use normal function syntax/ object initialization/MethodDefinition syntax like get NAME () { BODY } instead of compact "arrow function syntax".

But maybe you really like arrow functions; maybe you use the arrow function for another reason which a normal function syntax cannot replace; you may need a different solution.

For example, I notice OP uses this, you may want to bind this lexically; aka "non-binding of this"), and arrow functions are good for that lexical binding.

You can still use an arrow function with a getter via the Object.defineProperty technique, specifically with the accessor descriptor approach:

{
  ...
  Object.defineProperty(your_obj, 'status', { 
     get : () => this.xhr.status 
  });
  ...
}

See mentions of object initialization technique (aka get NAME() {...}) vs the defineProperty technique (aka get : ()=>{}). There is at least one significant difference, using defineProperty requires the variables already exists:

Defining a getter on existing objects

i.e. with Object.defineProperty you must ensure that your_obj (in my example) exists and is saved into a variable (whereas with a object-initialization you could return an object-literal in your object initialization: {..., get(){ }, ... }). More info on Object.defineProperty specifically, here

An advantage of the Object.defineProperty(...) approach is that you can run the code in a loop (i.e. define multiple properties)

Another difference between the two approaches is when you use get on an class vs defineProperty on an instance of a class:

When using get the property will be defined on the instance's prototype, while using Object.defineProperty() the property will be defined on the instance it is applied

Object.defineProperty(...) seems to have comparable browser support to the get NAME(){...} syntax; modern browsers, IE 9.

Notice the other options available to you when using Object.defineProperty(...):

  • enumerable: set to true if you want to enumerate/iterate over your new property using Object.keys
  • configurable : set to true if you want to redefine or delete your property

Upvotes: 77

apsillers
apsillers

Reputation: 115950

According to the ES2015 grammar, a property on an object literal can only be one of three things:

PropertyDefinition:

  • IdentifierReference
  • PropertyName : AssignmentExpression
  • MethodDefinition

The only one of these type that allows a leading get is MethodDefinition:

MethodDefinition :

  • PropertyName ( StrictFormalParameters ) { FunctionBody }
  • GeneratorMethod
  • get PropertyName ( ) { FunctionBody }
  • set PropertyName ( PropertySetParameterList ) { FunctionBody }

As you can see, the get form follows a very limited grammar that must be of the form

get NAME () { BODY }

The grammar does not allow functions of the form get NAME = ....

Upvotes: 192

Related Questions