Hacker News new | ask | show | jobs
by jallmann 3799 days ago
Off-topic, but am I the only one who thinks that classes are the most puzzling feature of ES6?

How is writing "class Blah extends Component { ... }" any better than "Blah = Preact.createComponent({ ... })", except to save a few keystrokes?

ES6 is full of syntactic sugar to improve readability, but classes substantially increase the "surface area" of the language for... what benefit? Static analysis and tooling, maybe? In that case, why not wait until ES7 is fully baked to build interesting features around the type system, instead of making yet another Java derivative...

4 comments

Well for one 'class Foo extends Bar' will work without any further code to make inheritance work in the way you'd expect, including use of super() etc. Whereas your second example is using non-trivial framework code, that some framework author has to write. See Backbone's extend() for a clear example of what is required [0]. That's work that every framework author is potentially going to implement differently, needlessly.

And the fact that almost every major framework has implemented something similar themselves is proof enough (for me at least) that the ES6 sugar is valuable. It has nothing to do with Java, it's simply a useful pattern that everybody was already using.

[0] http://backbonejs.org/docs/backbone.html#section-247

A note that using extends Component will cost you the function auto-binding that [p]react.createClass provides. In my specific case, using extends produced code that read more poorly.
But it's sad that not more framework authors tried StampIt or similar instead of reimplementing inheritance (more or less badly)

https://github.com/stampit-org/stampit

The question is whether that ~15 lines of code, written once, is worth the substantial increase in the surface area of the language, especially when overlapping so much with the existing prototypal inheritance mechanism. The choice to use Java/C++-style inheritance is a design pattern that doesn't necessarily reflect the only (or even the best) way to accomplish things.
ES6 classes do not use Java/C++ style inheritance, they are still the same as writing:

  function Foo() {

  }

  Foo.prototype = Object.create(Parent.prototype);

  ....
It's just sugar, nothing more.
The semantics of JS classes are still different in enough subtle ways: constructors and constructor subclassing, (lack of) object properties, hoisting, etc. That is on top of the new keywords, new function syntax, etc. All that needs to be mapped onto the model of "classical" Javascript in order to completely understand the language. There are enough gotchas there to disqualify JS classes from being simply sugar.
You can add object properties to a ES6 class's prototype, no?

EDIT: Just tested in Firefox and indeed you can.

Not in the class declaration, though. Why force the programmer to go through the prototype, when ES6 provides such a "convenient" abstraction around it?
Being a C++ developer during the day and a web dev at night, this syntactic sugar is actually a breath of fresh air.
I'm not yet convinced that it's just syntactic sugar. For example, what (generic) code is `super` syntactic sugar for?

Even if it is just syntactic sugar, that syntactic sugar makes it much more approachable for devs who want to use classical inheritance (not that I'd encourage that).

> what (generic) code is `super` syntactic sugar for?

  super.propertyOnSuper ~= this.__proto__.propertyOnSuper

  super() in constructor ~= ParentConstructor.call(this)
and some tools provide such things like this.super_:

https://github.com/isaacs/inherits/blob/3af5a10c6b51f9e99d9f...

Thanks for the response. If the choice is between manually specifying that (type of) code for every kind of object (and likely moving to a #create factory method) or using a native syntax for class declaration, I can see why people would choose the latter.
It's to a degree for people who are not primarily JS developers and often have no clue about prototypical inheritance. It also to a good degree reflects how V8 or some other engine actually treating your code under the hood.
The language surface area has already increased. The decision has been made.
I could not disagree more.

To me the readability benefit of classes, "extends" and "static" that work intuitively, "constructor", "super", etc. is immense, especially when you pair with something like Facebook Flow that let you declare the members with types. I consider it one of ES6's most compelling features. No more writing out "MyClass.prototype" just to declare basic classes with methods.

Absolutely -- having a typed object structure helps with tooling, as I mentioned. There are a lot of nice features that can be built around a solid type system to increase expressivity and improve safety. JS classes, as implemented, are an uninspiring facsimile of OO APIs, adding a lot of new syntax while papering over just enough semantic differences that it feels like a bit like an admission of defeat for the old paradigm.

I don't write nearly enough JS to say there is unequivocally a better way to write programs, but it's a bit disappointing that no one has figured out more advantageous ways to leverage the nature of the language without, IMO, leaning so much into cultural "learned behavior" from other OO languages.

Not to pile on here, but I try to use pure functions instead of Components as often as I can. The class keyword is sugar, sure, but like others have said - that ship has sailed. Personally, I just like that it's a language feature, since Components are the only time I ever use the class keyword my brain treats them as a 1:1 mapping. Perhaps it has something to do with both Classes and Components having a defined lifecycle? Cheers.
It's enlightening to hear why people seem to like this feature so much, so thanks for chiming in. While I'm still mystified (probably due to my PL tastes more than anything), I'll stop complaining for today.
There's not going to be any interesting features around the type system.

There's no change in the type system. Javascript is still a prototype based language.

There's no real value to a class system in a dynamic language, beyond synthetic sugar. Arguable prototypes are better since you don't get to question "if everything is an object, and classes are objects then what class is a class of?"

With ES7 decorators, you can put a mixin into a class... which gives you class sugar + traits, so essentially multiple inheritance without the downsides of it.

ES7 can be enabled today via Babel.