I have many question about ES6 classes.
What's the benefit of using class
syntax? I read that public/private/static will be part of ES7, is that a reason?
Moreover, is class
a different kind of OOP or it still JavaScript's prototypical inheritance? Can I modify it using .prototype
? Or is it just the same object but two different ways to declare it.
Are there speed benefits? Maybe it's easier to maintain/understand if you have a big application like big app?
The new
class
syntax is mostly, though not entirely, syntactic sugar (but, you know, the good kind of sugar). It markedly simplifies writing constructor functions and the objects they assign as prototypes to the objects they create, especially when setting up inheritance hierarchies, which was error-prone with the ES5 syntax. But unlike the old way,class
syntax also enablessuper.example()
for supercalls (which are notoriously hard to do the old way) as well as property declarations, private fields, and private methods (including static ones).(Sometimes people say you have to use
class
syntax if you want to subclassError
orArray
[which couldn't be properly subclassed in ES5]. That's not true, you can use a different ES2015 feature,Reflect.construct
[spec, MDN], if you don't want to useclass
syntax.¹)It's the same prototypical inheritance we've always had, just with cleaner, more convenient, and less error-prone syntax if you like using constructor functions (
new Foo
, etc.), plus some added features.Yes, you can still modify the
prototype
object on the class's constructor once you've created the class. E.g., this is perfectly legal:By providing a specific idiom for this, I suppose it's possible that the engine may be able to do a better job optimizing. But they're awfully good at optimizing already, I wouldn't expect a significant difference. One thing in particular about
class
syntax is that if you use property declarations, you can minimize the number of shape changes an object goes through when being constructed, which can make interpreting and later compiling the code a bit faster. But again, it's not going to be big.Briefly: If you don't use constructor functions in the first place, preferring
Object.create
or similar,class
isn't useful to you.If you do use constructor functions, there are some benefits to
class
:The syntax is simpler and less error-prone.
It's much easier (and again, less error-prone) to set up inheritance hierarchies using the new syntax than with the old.
class
defends you from the common error of failing to usenew
with the constructor function (by having the constructor throw an exception).Calling the parent prototype's version of a method is much simpler with the new syntax than the old (
super.method()
instead ofParentConstructor.prototype.method.call(this)
orObject.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)
).Property declarations can make the shape of the instances being created clearer, separating it from the constructor logic.
You can use private fields and methods (both instance and static) with
class
syntax, and not with ES5 syntax.Here's a syntax comparison (without private members) for a hierarchy:
Example:
vs.
Live Example:
As you can see, there's lots of repeated and verbose stuff there which is easy to get wrong and boring to retype (I used to use a script for it, back in the day, before
class
came along).I should note that in the ES2015 code, the
Person
function is the prototype of theEmployee
function, but that's not true in the ES5 code. In ES5, there's no way to do that; all functions useFunction.prototype
as their prototype. Some environments supported a__proto__
pseudo-property that might have allowed changing that, though. In those environments, you could do this:If for some reason you wanted to do this with
function
syntax instead ofclass
in an ES2015+ environment, you'd use the standardObject.setPrototypeOf
instead:But I can't see any strong motivation for using the old syntax in an ES2015+ environment (other than to experiment with understanding how the plumbing works).
(ES2015 also defines a
__proto__
accessor property that is a wrapper forObject.setPrototypeOf
andObject.getPrototypeOf
so that code in those non-standard environments becomes standard, but it's only defined for legacy code and is "normative optional" meaning an environment is not required to provide it.)¹ Here's how you'd use
Reflect.construct
to subclassError
(for instance) if you didn't want to useclass
syntax: