3

This is related to an old question but I'm specifically asking about extending a new ES6 class using the old way of writing a function.

The following code doesn't work.

class X {
    a;
    constructor(a) {
        this.a = a;
    }
}
X.call({}, 3); // Uncaught TypeError: Class constructor X cannot be invoked without 'new'

Is there a way to indirectly call the constructor function? For example, is it possible for me to use the old-fashioned prototypical inheritance to make a Y?

function Y(a) {
    X.call(this, a); // this doesn't work here, can't use super as well
}
Y.prototype = Object.create(X.prototype);
Object.setPrototypeOf(Y, X);
const y = new Y(12);
Michael Tsang
  • 678
  • 5
  • 16
  • 1
    I'm curious, why use a traditional function rather than `class` when you're extending a constructor created with `class` and you're using ES2015+? – T.J. Crowder Oct 21 '20 at 16:21

1 Answers1

2

Yes, you can use Reflect.construct and new.target:

function Y(a) {
    return Reflect.construct(X, [a], new.target || Y);
}

Live Example:

class X {
    a;
    constructor(a) {
        this.a = a;
    }
}

function Y(a) {
    return Reflect.construct(X, [a], new.target || Y);
}
Y.prototype = Object.create(X.prototype);
Object.setPrototypeOf(Y, X);
const y = new Y(12);
console.log(y.a); // 12

or if you want to pass along all provided arguments:

function Y(...args) {
    return Reflect.construct(X, args, new.target || Y);
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875