Javascript: why should not use getters/setters?

Created on 10 Aug 2018  路  13Comments  路  Source: airbnb/javascript

I'm so confused with "24.2 Do not use JavaScript getters/setters as they cause unexpected side effects and are harder to test, maintain, and reason about. "

Getters/setters, as we all know, is a standard way in ES6, but why you guys say "do not use"?
What are the side effects?
What are we worrying about?

Can we support more descriptions about it ?

question

Most helpful comment

@ljharb, I have some comments about your arguments:

One of the least important is performance - they're massively slow.

Only for plain JS objects. For ES6 classes the difference is negligible. Proof. So why ban them everywhere?

Even if "for consistency" - why even use computed gets/sets (in any form) on a plain object? The approach to writing plain functional objects is usually drastically different from classes' anyway.


The most important is because it reduces clarity and maintainability

Any explanation on this? Couldn't find any concrete or up-to-date arguments anywhere on the web. Refactoring difficulty is the same, since all refactoring tools in IDEs treat getters and setters as functions.

Clarity, in this particular case, depends on the point of view. It's obvious for me that getters or setters should not be used for heavy computational tasks.
Computing a full user's name is fine. So why ban this?

Getters and setters are intended to hide computational functionality. They are made specifically so you wouldn't know if the value is computed. This is the point.
So the end-user of a library does not have to explicitly know, which value is computed and which isn't.

If this is the actual reason for a full ban on getters and setters - then why not state it as such? Some reasoning is always better than no reasoning.


all for the insignificant benefit of avoiding () or (x).

This is not the benefit. This is taste. Just as your personal dislike for getters and setters. This should be understandable. So, minding this, how come your taste is more valid than others' taste? This is very far from "a mostly reasonable approach". Style guides are made to break people's tastes in benefit of a uniformal approach to writing code.

The benefit is in freeing the end-user from cognitive load about what is computed and what is not. When an operation takes O(n) - there is no real difference when its result is saved into a variable or returned from a function. Hence, there's no matter if the property is computed or not.

So, keeping everything of what I wrote in mind, I'd re-formulate the end-reason for at least a partial getters/setters ban as following:


Do not use JavaScript getters/setters in plain javascript object. Only usages in classes are allowed.

> Why? Getters and setters obscure value computations form the end-user and are up to 30 times slower when used in plain JS objects.

All 13 comments

So so many reasons. One of the least important is performance - they're massively slow.

The most important is because it reduces clarity and maintainability, all for the insignificant benefit of avoiding () or (x).

Getters and setters are "standard" but so is "with" and "eval" - "in the spec" is never a sufficient justification to use something.

Also #757, #1367, #670.

Thank you,plz close the issue :)

@ljharb, I have some comments about your arguments:

One of the least important is performance - they're massively slow.

Only for plain JS objects. For ES6 classes the difference is negligible. Proof. So why ban them everywhere?

Even if "for consistency" - why even use computed gets/sets (in any form) on a plain object? The approach to writing plain functional objects is usually drastically different from classes' anyway.


The most important is because it reduces clarity and maintainability

Any explanation on this? Couldn't find any concrete or up-to-date arguments anywhere on the web. Refactoring difficulty is the same, since all refactoring tools in IDEs treat getters and setters as functions.

Clarity, in this particular case, depends on the point of view. It's obvious for me that getters or setters should not be used for heavy computational tasks.
Computing a full user's name is fine. So why ban this?

Getters and setters are intended to hide computational functionality. They are made specifically so you wouldn't know if the value is computed. This is the point.
So the end-user of a library does not have to explicitly know, which value is computed and which isn't.

If this is the actual reason for a full ban on getters and setters - then why not state it as such? Some reasoning is always better than no reasoning.


all for the insignificant benefit of avoiding () or (x).

This is not the benefit. This is taste. Just as your personal dislike for getters and setters. This should be understandable. So, minding this, how come your taste is more valid than others' taste? This is very far from "a mostly reasonable approach". Style guides are made to break people's tastes in benefit of a uniformal approach to writing code.

The benefit is in freeing the end-user from cognitive load about what is computed and what is not. When an operation takes O(n) - there is no real difference when its result is saved into a variable or returned from a function. Hence, there's no matter if the property is computed or not.

So, keeping everything of what I wrote in mind, I'd re-formulate the end-reason for at least a partial getters/setters ban as following:


Do not use JavaScript getters/setters in plain javascript object. Only usages in classes are allowed.

> Why? Getters and setters obscure value computations form the end-user and are up to 30 times slower when used in plain JS objects.

@Raiondesu i'm afraid a microbenchmark like jsperf isn't "proof" of anything; you'd need to run your actual code in your actual application to determine if the performance matters.

You shouldn't be hiding computation - properties should be properties, and functions should be functions. Deviating from that harms clarity and maintainability.

We will not be permitting getters and setters in classes, but you're welcome to fork the guide and make whatever changes you see fit!

You shouldn't be hiding computation - properties should be properties, and functions should be functions.

Refusing to hide computation goes against enapsulation.

Deviating from that harms clarity and maintainability.

Again, what are those giant unholy maintainability costs you're talking about?

I could only find sources arguing that getter and setter methods are much harder to maintain (also this and this and this), in contrary to your words.


After all, I'm not saying that you have to permit the usage of getters and setters in your guide. It's your guide, after all.

I'm saying that the reasoning in the guide is not on pair with your arguments. And this is a lot of problem for a single entry in the most referenced JS style guide in the web. And a lot of responsibility.

Should we consider fixing the reasoning then?

Encapsulation is about hiding implementation details, but "there are effects" is not an implementation detail - it's part of the public API. Additionally, since you can reflect to determine if something is a getter, encapsulation here is not possible.

I find the reasoning correct as-is.

I find the reasoning correct as-is.

None of those reasons, which would help explain what they cause unexpected side effects and are harder to test, maintain, and reason about actually means... are listed in the guide though... where is the harm in making the explanation in the guide as clear as possible?

I see zero examples of unintended side effects, they are no different to test than any other JS which makes them just as simple to maintain...

Please cite cases for these they cause unexpected side effects and are harder to test, maintain, and reason about so their is something to understand the justification for this setting.

I understand time elapsed since the discussion, but I wonder whether this is good to use getters setters in the first place. If you try to access a variable by name, and the variable doesn't exist, first of all JS will try to find it in the prototype chain, and after that will execute getter. Am I right?

@host510 no, that's not correct. "getters" are an object property thing, not a variables thing. If you try to access a property on an object, it will look for it on the current object, and if missing, will look up the prototype chain one at a time until it finds it. When it finds it, if it's an accessor property, it invokes the getter.

No, it's not good to use getters/setters in the first place, which is summarized in the issue above.

which is summarized in the issue above

Which is not summarized anywhere in this issue (nor in the guide) yet, and people here spent a good deal of effort to get the proper explanation from @ljharb.
This explanation is still not present at the moment (and I don't consider "harder to reason about" and "performance issues" as a proper explanations).

There was a good and meaningful request from @ktiedt earlier, which was left unanswered.

None of those reasons, which would help explain what they cause unexpected side effects and are harder to test, maintain, and reason about actually means... are listed in the guide though... where is the harm in making the explanation in the guide as clear as possible?

I see zero examples of unintended side effects, they are no different to test than any other JS which makes them just as simple to maintain...

Please cite cases for these they cause unexpected side effects and are harder to test, maintain, and reason about so their is something to understand the justification for this setting.

I don't have any concrete cases off the top of my head. However, using a getter has the benefit of "you don't have to type ()" and has the downside of "it looks like a normal property, but it's actually a function call". In my experience, this has caused a large amount of friction when investigating bugs, and when understanding code as written.

JS isn't Ruby. If you want a property access/assignment to have special behavior, make it a normal method. It's not performant, idiomatic, or obvious when you use a getter/setter.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ryankask picture ryankask  路  3Comments

stephenkingsley picture stephenkingsley  路  3Comments

surfaceowl picture surfaceowl  路  3Comments

zurfyx picture zurfyx  路  3Comments

tunnckoCore picture tunnckoCore  路  3Comments