Closed a-ejs closed 5 years ago
Another use case would be defining class methods in different files:
import {someMethod} from "somewhere";
export class Thing {
method = someMethod;
}
I don't think there's a 'nice' way to do this as of now.
;)
This is an updated summary of the problems I see with new syntax. I might update this with more points later.
It is unintuitive
Given that this:
is practically identical to:
it is not entirely unreasonable to expect
to be the equivalent of
but it isn't.
Likewise, in this class definition:
method
foo
ofB.prototype
expectedly takes priority over inherited methodfoo
fromA.prototype
:But if
A
were defined like this:behavior would be radically different, which is not apparent.
It is inconsistent
It is also inconsistent with similar constructs in the language or this very proposal. For example, if you add the keyword
static
, this:expectedly does become identical to
Object literals use somewhat similar syntax, so this:
is also practically same as
Proposed class fields on instances is not consistent with any of this behavior.
It does not add any clarity
Properties on class instances are initialized in the constructor, like so:
Everything about this example is clear. It defines a constructor function that, when called, sets the property
listOfThings
ofthis
to a new array. There's also zero ambiguity to when this assignment is done and how it works with inheritance.Proposed syntax simplifies it to:
This is, supposedly, somehow an improvement. But where it saves the programmer the need to type
this.
in front of the definition, it makes the behavior much more implicit and less apparent.It changes the meaning of
class
syntaxClasses in JavaScript is just an abstraction, syntactic sugar, whatever you want to call it, over its prototype-based inheritance. A "class" is defined by a constructor function and its prototype. So,
class
syntax is just an easier way to define that function and the prototype.Body of
class
definition describes properties of the prototype or the function itself, only theconstructor
property being somewhat special since it describes the function itself. But it still exists as a method property (syntactically) and even goes into the prototype (asA.prototype.constructor
) - that's also pretty neat. (Although that behavior is unrelated to class syntax, it's just a nice touch. And it's consistent!)New syntax invalidates all of that. Now, the class body describes both what the constructor is and what it does, in one place. And since it doesn't replace the
constructor() {}
syntax, what it does is now defined both inside and outside the function body, something extremely unusual and not achievable with other syntax.It mixes function code with normal code
As far as I know, this behavior is not present anywhere else in the language.
A function's body is a sequence of statements that's executed when the function is called, as opposed to non-function object literals that are evaluated right away.
Class body is not a function body. It describes the function and its prototype as an object. With instance fields, class body becomes mixed code, where some parts are evaluated right away, and some are evaluated with the constructor:
This is very unusual for JS. Just because similar behavior exists in other languages like C++ doesn't necessarily mean it would work perfectly fine in JS, especially considering how C++ classes and JS prototype inheritance have very little in common besides general purpose.
Imagine if function properties could be defined within its body:
This isn't much different from class fields.
Summary
This syntax provides very little, if any, benefit for all the downsides that it has.
I don't see how current way of initializing instance properties is so bad that it needs to be simplified or changed in the first place.
New syntax is deceiving, confusing, does not promote good practice. Someone who doesn't know better could easily create more instances than needed of the same thing without realizing, as an example. It can easily become another "ugly" part of the language, for the lack of a better word.
It's very strange to me that apparently very few people seem to see an issue with all this.
original issue text below
The following code:
defines a "class"
foo
with "methods"bar
andbaz
- "class" and "methods" being quoted because that's just syntactic sugar over defining a constructor function and a prototype, like so:So if I were to swap out a method definition for another value, I would expect something like this:
to become (identical to):
but instead it becomes:
which is counter-intuitive, and frankly not that useful (saves typing the
this.
part in constructor, whereas adding properties to the prototype remains a pain in the ass), but I think the former should be the focus.So why does it work that way? Seems much more confusing than it is useful.
Likewise, the whole concept of "private fields" brings in too much complications while not being a very useful addition in general to say the least, and I don't think it belongs in the language - but that's just my opinion (and isn't the subject of this issue).