When running the following code on Node.js 4.2.1:
'use strict';
var util = require('util');
class MyClass {
constructor(name) {
this.name = name;
}
}
function MyDerived() {
MyClass.call(this, 'MyDerived');
}
util.inherits(MyDerived, MyClass);
var d = new MyDerived();
I get the following error:
constructor(name) {
^
TypeError: Class constructors cannot be invoked without 'new'
I wonder if it is at all possible to inherit old-style JavaScript "classes" from ECMAScript 6 classes? And, if possible, then how?
JavaScript does not support multiple inheritance. Inheritance of property values occurs at run time by JavaScript searching the prototype chain of an object to find a value.
What are ES6 classes? In ES6, the "class" keyword and associated features are a new approach to creating prototype constructors. They are not true classes in a way that would be familiar to users of most other object-oriented languages.
When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.
We use the extends keyword to say that this class inherits from another class. The Professor class adds a new property teaches , so we declare that. Since we want to set teaches when a new Professor is created, we define a constructor, which takes the name and teaches as arguments.
There's not really a way out once you've opted in to class
syntax.
The problem is that inheritance in ES6 is done by late-initialising the this
keyword with the return value from super()
, which is a constructor call like with new
. The old idiom of "applying" (.call()
) the parent constructor on the currently "uninitialised" child instance does work no more.
What you can still do is to resort to "parasitic inheritance" - you'll have to explicitly construct the instance, extend it, and return
it:
function MyDerived() {
var derived = new MyClass('MyDerived');
… // set up properties
return derived;
}
When you do this with new MyClass
, you won't get the prototype set up correctly however. For that, you will need to use the new ES6 Reflect.construct
function, which takes the child class as an optional third parameter:
function MyDerived() {
var derived = Reflect.construct(MyClass, ['MyDerived'], new.target||MyDerived);
… // set up properties
return derived;
}
This has the additional benefit that MyDerived
doesn't need to be called with new
any more (as long as you supply MyDerived
when new.target
is empty).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With