tc39 / proposal-class-public-fields

Stage 2 proposal for public class fields in ECMAScript
https://tc39.github.io/proposal-class-public-fields/
487 stars 25 forks source link

ES6 classes need fixing #35

Closed nmn closed 8 years ago

nmn commented 8 years ago

We're adding all this extra syntax just for ES6 classes. Case in point instance and static fields but also decorators.

Decorators won't work with normal functions. But really decorators are nothing more than higher order functions. We shouldn't need new syntax for this stuff.

Instead, using the class fields, we could make the class syntax a little more sane. (It's too late for a re-write)

Problems with ES6 classes

  1. Functions/methods are given special status: Javascript has always had first-class functions. In the ES5 days writing classes in JS was clunky, but ES6 classes, methods have become something different than simple values. Currently, all methods in a class body get attached to the prototype. But there is no way to attach NON-function values to the prototype anymore.
  2. You can no longer use the word function.

You can't write this:

class X {
  someMethod: function() {... }
}
// OR
class X {
  someMethod = function() {... }
}

With the fields proposal, the second would work but would get attached to each instance, instead of the prototype.

Conclusion

Let me just end here and say ES6 classes have problems, and before we try hacking around it's flaws we should consider making it better.

So perhaps:

class X {
  someMethod = function() {... }
}

should be equivalent to

class X {
  someMethod() {... }
}

And decorators can be applied like so:

class X {
  someMethod = decorate(function() {... })
}

Instead of trying to look more and more like other languages (cough Java cough). Maybe we should try to keep Javascript more internally consistent.

PS:

I also really dislike the requirement of semi-colons at the end of field declarations. Does it really need to be there? I know about the computed names for methods being an edge-case, but surely there's another way around that. Maybe the semi-colons can be optional, just like the rest of Javascript.

ljharb commented 8 years ago
  1. decorators will likely work with normal functions, it's still an open question as I understand it. Certainly something that only works for "class" syntax will have a tough time making it all the way through the process.
  2. decorators aren't part of this proposal, so unless there's a cross-cutting concern (something in either proposal that conflicts with each other), they're not particularly relevant.
  3. "not using the word function" is generally considered an improvement, since it removes boilerplate.
  4. object literals have concise methods as well, so ES6 classes are not special in this regard, and the most common consensus around style guides for this is to always use concise methods in every context.
  5. there is no requirement for semicolons. the same ASI rules that apply throughout JS will apply here - a semicolon is only required when the statement on the next line is ambiguous such that the semicolon won't be automatically inserted.
nmn commented 8 years ago

@ljharb

Note: not trying to argumentative here, but I need to clarify my point.

1 & 2. decorators are currently blocked for functions as functions 'hoist'. But in any case I understand that it's a completely separate proposal, and I only brought it up to point out the problems with ES6 class syntax.

3 & 4. Not using the word function is an improvement. But I dislike the fact that you can no longer use the word function. That is actually a bad example. The bigger problem is that you can no longer use references to functions defined externally:

function worksAsAMethod () {...}

class X {
  myMethod: worksAsAMethod // doesn't work
  myMethod= worksAsAMethod // will work with this proposal, but won't get put on the prototype.
}

5) I may be incorrect in this. But I saw an issue explaining how this proposal makes semi-colons mandatory after field definitions. If they are only needed when the next field/method starts with a [ then ignore my statement about semi-colons here.

ljharb commented 8 years ago

What's the use case for defining a function outside of a "class" body and then installing it on a prototype, versus defining a new function that dispatches to the function in question?

nmn commented 8 years ago

@ljharb You offer a good workaround. But I ask we should even need such a workaround. I'm not trying to say ES6 classes don't work. They just don't work well. Bring weird limitations that don't 'fit' in with javascript's dynamic nature.

jeffmo commented 8 years ago

Cleaning up issues. Feedback certainly welcome, but I'm not too sure what's actionable here so going to close this out since it's been a while.

bathos commented 7 years ago

Wow @nmn ... I know it’s far too late, but I wish you had been on the tc39 board two years ago :)