Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the argument for using ES6 getters and setters over getProperty/setProperty convention?

class Foo {
    getName = () => this.name;

    setName = (name) => this.name = name;
}

and

class Foo {
    get name () {
        return this.name;
    }

    set name (name) {
        this.name = name;
    }
}

I can think of several examples where ES6 getters are at a disadvantage, e.g.

You cannot write a getter that will return a value based on a parameter value:

/**
 * Returns an instance of Card associated with an element.
 *
 * @param {HTMLElement} element
 * @return {Card|undefined}
 */
getCard = (element) => {
    return _.find(this.index, {
        element: element
    });
};

That's okay, however, if you use this and ES6, you are introducing code style inconsistency.

You cannot distinguish between a direct property access and method access.

class Foo {
    get name () {
        return this.name;
    }

    get expensive () {
        // An operation that takes a lot of computational power.
    }

    get randomValue () {
        // Returns random value.
    }
}

let foo = Foo();

foo.name;
foo.expensive;
foo.randomValue;

The disadvantage is that it is not intuitive that a property that you are accessing might require heavy computational power (and therefore should be memoized) or that it changes every time you access it.

Finally, getters/setters do not work with arrow functions. Invalid example:

class Foo {
    get name = () => {
        return this.name;
    }

    set name = (name) => {
        this.name = name;
    }
}

Which exposes them to the context issues.

What is the advantage of using ES6 getters and setters over the conventional get{PropertyName} and set{PropertyName} abstraction?

like image 298
Gajus Avatar asked Aug 20 '15 09:08

Gajus


People also ask

What's the advantage of using getters and setters?

1. The getter and setter method gives you centralized control of how a certain field is initialized and provided to the client, which makes it much easier to verify and debug. To see which thread is accessing and what values are going out, you can easily place breakpoints or a print statement. 2.

What is the purpose of getter and setter methods in JavaScript?

Getters and setters allow you to define Object Accessors (Computed Properties).

What is the purpose of usage getters for JavaScript objects?

Getters give you a way to define a property of an object, but they do not calculate the property's value until it is accessed. A getter defers the cost of calculating the value until the value is needed. If it is never needed, you never pay the cost.

Are getters and setters necessary in JavaScript?

A getter or setter can be very useful at times, but they only need to be used when their specific functionality is required - otherwise plain property access without a getter or setter can be just fine. A getter has use when you want to run some code every time a property is requested.


1 Answers

You cannot distinguish between a direct property access and method access.

This is the main argument in their favour.

One of the weirdest great pains of writing classic Java-style OO code is that any object with an exposed property on it has to have getters and setters written, and a huge amount of boilerplate comes rolling out of this, especially for large data-structure type objects (e.g. DTOs).

The reasoning for all of these is that you can't just make properties public, because otherwise you can't ever add logic to them without breaking the API (e.g. logic to only allow settings certain values, or to refactor and store a property in a slightly different way while still exposing the same external API, or similar). See https://softwareengineering.stackexchange.com/questions/176876/why-shouldnt-i-be-using-public-variables-in-my-java-class for some typical arguments around this.

I think you could comfortably say that this has been taken to its logical extreme in recent years, but that doesn't mean it's wrong; by exposing a public field for direct access you are indeed exposing the internal implementation of how you're storing that data, and that means you can't change it as easily or safely any more.

ES6 getters/setters fix this. The fact that something is readable as a direct property on an object no longer tells you anything about the implementation of that property. It could have been a field originally, but recently turned into a ES6 property accessor instead, without the API changing. The implementation of the property is hidden from the rest of your codebase, and is therefore easier to change.

The disadvantage is that it is not intuitive that a property that you are accessing might require heavy computational power (and therefore should be memoized) or that it changes every time you access it.

You're right, this is a risk. That's also a gotcha with any getX() though; there's a strong convention suggesting that nice simple methods like 'getName()' shouldn't ever be doing expensive things behind the scenes, even if they are methods, and if you break that you'll almost certainly end up catching people out (including yourself, 6 months from now)

Moving to properties doesn't change this, but you're right that ES6 means you're no longer guaranteed to be safe for simple property accesses. The answer is really just that you have to make sure you (and everybody else) sticks with convention and Principle of Least Astonishment: as with existing simple looking getters and setters, ES6 property accessors should do simple cheap things, and shouldn't have strange side effects elsewhere.

like image 50
Tim Perry Avatar answered Oct 18 '22 15:10

Tim Perry