Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why not fields? #21

Closed
zenparsing opened this issue Mar 8, 2018 · 6 comments
Closed

Why not fields? #21

zenparsing opened this issue Mar 8, 2018 · 6 comments

Comments

@zenparsing
Copy link
Owner

Public fields (including static public) are very widely requested by the community, and the proposed semantics are simple and readily implementable. I don't see a good reason to withdraw the proposal.

Here are my thoughts:

JS has no such thing as "fields". There are properties and there are internal slots/instance variables. When we attempt to clump them together under a single unifying concept named "fields" we get all kinds of problems. For instance:

  • Static private fields don't work because of the prototype/TypeError issue.
  • Private methods are kind of like properties (e.g. accessors) but kind of like internal slots. Which are they?
  • Strange differences between obj.#x and obj['#x'].
  • Leakage when decorators are applied to private things.

Additionally, fields tend to be an attractive nuisance leading developers towards these anti-patterns:

  • Eliding derived class constructors that actually do meaningful work.
  • Creating "psuedo-methods" using fields initialized to arrow functions.

I re-reviewed the original motivation document. The stated motivations are:

  • Public fields allows better integration with tools and type system supersets of JS. I must admit that I don't understand this. What does a type-system-supporting superset of JS have to do with adding things to JS?
  • Public fields allows eliding derived class constructor definitions in some scenarios. The use cases to which this applies forms a very narrow band. The notable use case is React. Should JS be optimizing itself for a single framework, when frameworks come and go?
  • Public fields allows the programmer to express the "shape" of instances in a more declarative fashion. Although I sympathize with this desire, I believe the better way to move toward more declarative "shape" is to use instance variable declarations.
  • Public static fields allow the programmer to attach things to the constructor inside of the class body. You can do the same (and more) with class initializer blocks.

While I think public "fields" makes sense on their own, the "fields" concept does not generalize well to encapsulated per-instance state and hidden methods.

Here's the main idea: if we choose to have public fields (which have some minor problems of their own), then we will be lead irresistibly toward private fields and private methods (which have a bunch of problems). The upside of public fields is pretty small, while the downside of private fields and methods is fairly large. Therefore, it is better not to have public fields at all, and choose a different syntax for instance variables.

@littledan
Copy link
Collaborator

I'd like to make it easy for people to refactor from public to private. I think this can improve the uptake of private fields and make them easier to learn. The private methods explainer walks through an incremental update example. Maybe it would be helpful to do a similar exercise for this proposal.

@zenparsing
Copy link
Owner Author

Great idea. I've started on a refactoring document here.

@zenparsing
Copy link
Owner Author

Closing in preparation for public review. I'll add a "why not fields" document shortly.

@allenwb
Copy link
Collaborator

allenwb commented Mar 12, 2018

I'll add a few points

  • The field proposal conflates two different things into a single syntactic declarator: private non-inherited, strictly encapsulated per-instance state; and public own properties. They have very different semantics Conflating them is a significant source of inessential complexity and conceptual confusion.

  • The wordless "variable" declaration form is new and unfamiliar to JS programmers. It is also a new source of ASI hazards.

  • Conflating own properties and hidden per instance state into into a single keywordless declarator forces the use of a special character prefix (#) to identify the hidden state variables. There has been very significant community feedback in opposition to both the # prefix in particular and the general concept of special character prefixing of identifiers.

  • "Public fields" add no capability that is not already available. JS programmer understand how to define and initialize own properties of class instance. They do it via assignment in the class constructor. "public field" declarations increase overall complexity but add no new essential capability.

  • One example of complexity introduced by field declaration is the semantics of field initializers. Their scoping is different from computed property name expressions and they require the added complexity of non-obvious evaluation sequencing of the various expression forms that can appear in a class body.

@ljharb
Copy link

ljharb commented Mar 12, 2018

They do it via assignment in the class constructor.

To match what public instance fields do, they'd have to Object.defineProperty in the class constructor.

@zenparsing
Copy link
Owner Author

To match what public instance fields do, they'd have to Object.defineProperty in the class constructor.

That is certainly true, but typically users don't need to use Object.defineProperty to get the behavior that they want.

If you add public fields to the language you of course must use [[DefineOwnProperty]] in order to avoid unintuitive edge cases around base class accessors. Again, I think this points back to the idea that public fields creates inessential complexity by muddying the concepts of "fields", "properties", and "instance variables".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants