Matías Fidemraizer
Matías Fidemraizer

Reputation: 64923

Call base class constructor without manually supplying arguments

Imagine that we've the following class:

class A {
       constructor(x, y, z) {
       }
}

class B extends A {
     constructor(x, y, z) {
         super(x, y, z);
     }
}

What if we want to call super(...) with arguments or rest arguments:

super.apply(this, arguments);
super.apply(this, args);

This won't work: super.* is not allowed before super().

Is there any alternative to avoid manually supplying arguments?

Upvotes: 0

Views: 92

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074295

Use spread notation:

super(...args);

E.g.:

class B extends A {
    constructor(...args) {
        super(...args);
    }
}

(super(...arguments) would also work.)

But it's worth noting that for the A and B shown, you don't need to provide a constructor for B at all. The default constructor¹ for a derived class is exactly as shown above, so:

class B extends A {
}

would do exactly the same thing.

Further examples below.

In a comment, you said there are 10 (!) parameters to the base class and you only need two of them in your subclass, and my impression is you meant the first two. If so:

class B extends A {
    constructor(first, second, ...rest) {
        super(first, second, ...rest);
        // Use `first` and `second` here...
    }
}

If you meant two in the middle, we can do that with destructuring as well:

class B extends A {
    constructor(...args) {
        super(...args);
        let {1: second, 2: third} = args;
        // Use `second` and `third` here...
    }
}

More Examples:

class A {
  constructor(x, y, z) {
    console.log(`A: ${x}, ${y}, ${z}`);
  }
}

// No constructor defined; gets default
class B1 extends A {}

// Explicit version of the default constructor
class B2 extends A {
  constructor(...args) {
    super(...args);
  }
}

// Using `arguments` instead:
class B3 extends A {
  constructor() {
    super(...arguments);
  }
}

// If the subclass accepts different args
class B4 extends A {
  constructor(q, ...rest) {
    super(...rest);
    console.log(`B4: q = ${q}`);
  }
}

class B5 extends A {
  constructor(...args) {
    super(...args);
    // They don't have to be called `y` and `z`, I'm just being consistent
    let { 1: y, 2: z } = args;
    console.log(`B5: y = ${y}, z = ${z}`);
  }
}

new B1(1, 2, 3);
new B2(4, 5, 6);
new B3(7, 8, 9);
new B4('q', 'x', 'y', 'z');
new B5('first', 'second', 'third');


¹ "the default constructor for a subclass is exactly as shown above" Note how this is different from languages like Java or C#, where the default constructor would accept no args and call super()/base() with no args.

Upvotes: 2

Keith
Keith

Reputation: 24191

class A {
       constructor(x, y, z) {
         console.log(x,y,z);
       }
}

class B extends A {
     constructor(x, y, z) {
         super(...arguments);
     }
}

let X = new B(1,2,3);

Upvotes: 3

Related Questions