How to fix the `class` keyword
axel at rauschma.de
Wed Mar 4 13:02:51 UTC 2015
I’m saying the following as someone who does not think that classes are perfect (I dislike that they look so different from what they are internally translated to), but they will “just work” for most people and they are backwards-compatible with much current code.
> Make class inheritance compositional similar to the way stamps are composed. <http://chimera.labs.oreilly.com/books/1234000000262/ch03.html#prototypal_inheritance_with_stamps> In other words, change the behavior of `extend`, or deprecate `extend` and replace it with something like a `compose` keyword that can compose any number of classes.
Traits (or mixins) are coming! A class will be the location where you assemble (any number of) traits. IMO, it’s better to have a different construct for this than to force classes to serve this use case. In my view, this is your most important point and traits are the answer.
> Deprecate `new`. `new` violates both the substitution principle and the open / closed principle. The `new` keyword is destructive because it adds zero value to the language, and it couples all callers to the details of object instantiation. If you start with a class that requires `new` (all classes in ES6) and you later decide you need to use a factory instead of a class, you can’t make the change without refactoring all callers. This is especially problematic for shared libraries and public interfaces, because you may not have access to all of the code using the class. You may think it doesn’t do any harm to just call a factory function with the `new` keyword, but the `new` keyword triggers behaviors that change what’s going on when the function is invoked. If you can’t count on the function to behave the same way for all callers, you can’t predict what the software will do. That’s bad.
> Make sure that `class` obeys the substitution principle when you switch from a class to a factory and vise verse. This is an important point, because if callers are counting on any behavior or property of a class, and you decide to change the implementation to a factory, you’ve just broken the calling code. Additionally, if callers are counting on the behavior of a factory, and you switch the implementation to a class, that’s similarly problematic, though as it stands, there’s no good reason to switch from a factory to a class.
You can easily return an instance of a subclass or any other object from a class constructor. Engines can an will optimize this so that there won’t be any difference between a factory function and a class in this regard. In other words: you can make the changes you are describing.
> The behavior of `this`. It always refers to the new instance in a class constructor. In a factory function, `this` is dynamic, and follows a completely different set of rules. Possible solution: deprecate `this` and instead refer to the class or function by name. A major drawback of this solution is that it would break `.call()`, `.apply()` and `.bind()`, unless we also change their behavior to override the function name reference.
This assumes that you want to go back and forth between classes and factory functions. If you don’t then `this` is not an issue.
I agree. Classes do have drawbacks, but they also have advantages: static analyzability, backwards compatibility, the ability to subclass built-ins. I can clearly feel your passion, but you are not being completely fair w.r.t. their pros and cons.
After traits (in ES7?), I don’t see anything *major* missing from your wish list. Things won’t be *exactly* like you want them, but you’ll be able to do everything you want to.
Dr. Axel Rauschmayer
axel at rauschma.de
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss