Before ES6 classes, a function could be used as a constructor:
function MyClass(a, b) {
}
Then, the following code is equivalent to a classic instantiation (like let thisObj = new MyClass("A", "B")
):
let thisObj = Object.create(MyClass.prototype)
// Here we know the `this` object before to call the constructor.
// Then, the constructor is called manually:
MyClass.call(thisObj, "A", "B")
… This technique was a way to know the this
object before calling the constructor. But Function.prototype.call()
doesn't work on an ES6 class constructor.
With ES6 we have Reflect.construct()
:
let thisObj = Reflect.construct(MyClass, "A", "B");
But it doesn't provide a way to call the constructor after the this
object is created.
Is it still possible to do that with ES6 classes?
I would have needed to keep this feature from ES5 to ES6 for a framework. The framework is responsible for instantiating components (which are ES6 classes). A component can create child components (in a tree of components, there is no inheritance here) from its constructor. Then, a child component can query the framework to get its parent from its own constructor. In this case, we have a technical limitation because the framework still doesn't have the return value of the parent component constructor. This is a regression compared to (a transpilation to) ES5.
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this .
Explanation: Constructors are the member functions which are called automatically whenever an object is created. It is a mandatory functions to be called for an object to be created as this helps in initializing the object to a legal initial value for the class.
No, you cannot call a constructor from a method. The only place from which you can invoke constructors using “this()” or, “super()” is the first line of another constructor. If you try to invoke constructors explicitly elsewhere, a compile time error will be generated.
Calling parameterized constructor from default constructor: A(){ this(5); System.out.println("hello a"); }
It's impossible to do that with ES6 classes. ES6 classes are supposed to be instantiated only with new
or Reflect.construct
.
Function-calling classes is currently forbidden. That was done to keep options open for the future, to eventually add a way to handle function calls via classes. [source: exploringjs]
See also:
Class instance isn't necessary this
object that appears in constructor, because ES6 class can return a value from constructor, which is considered class instance:
class Foo {
constructor {
// `this` is never used
return {};
}
}
A component can create sub-components from its constructor. Then, a sub-component can query the framework to get its parent from its own constructor
This pattern is not viable in ES6 classes. The limitation restricts this
from appearing before super
.
In order to reach particular classes in hierarchy, decorator pattern can be used to decorate a class when it's defined. This allows to modify its prototype on definition or put an intermediate class between a parent and a child. This approach solves a lot of framework-specific tasks like dependency injection and is used in modern frameworks (Angular, etc.).
A convenient way to do this is ECMAScript Next/TypeScript decorator. Here's an example that shows that a decorator allows to dynamically intercept child constructor and augment child prototype:
let BAZ;
class Foo {
constructor(foo) {
console.log(foo);
}
}
function bazDecorator(Class) {
return class extends Class {
constructor(foo) {
super(BAZ || foo);
}
get bar() {
return BAZ || super.bar;
}
}
}
@bazDecorator
class Bar extends Foo {
constructor(foo) {
super(foo);
console.log(this.bar);
}
get bar() {
return 'bar';
}
}
// original behaviour
new Bar('foo'); // outputs 'foo', 'bar'
// decorated behaviour
BAZ = 'baz';
new Bar('foo'); outputs 'baz', 'baz'
ES.next decorator is basically a helper function. Even without syntactic sugar, it is still applicable in ES6 with slightly different syntax:
const Bar = bazDecorator(
class Bar extends Foo { ... }
);
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