Asken
Asken

Reputation: 8041

ES6 pass an object to constructor and set property

Look at the below example:

class Parent {
    constructor({ parentOnlyArg = 'default value' } = {}) {
        this.parentOnlyArg = parentOnlyArg;
    }
}

class Child extends Parent {
    // this class and also any class inheriting from it
    constructor({ visibleStyle = 'inline' } = {}) {

        // I want to pass argument to super as an object
        super(/** args **/);

        this.visibleStyle = visibleStyle;
    }
}

class Child2 extends Parent {
    // Specifying parentOnlyArg as default will change the behaviour
    constructor({ parentOnlyArg = 'another parent value',
                  someOther = 'value' } = {}) {

        // I want to pass argument to super as an object
        super(/** args **/);

        this.someOther = someOther;
    }
}

Is it possible to pass on the constructor argument to super?

Seems like it was simpler than I thought

super(...arguments);

I can then create Child using

var c1 = new Child(); // c.parentOnlyArg = 'default value'
var c2 = new Child2(); // c.parentOnlyArg = 'another parent value'
var c3 = new Child({ parentOnlyArg: 'changed again' }); // c.parentOnlyArg = 'changed again'

Upvotes: 0

Views: 6283

Answers (2)

Tamas Hegedus
Tamas Hegedus

Reputation: 29906

You could use object destructuring with rest properties. It is not yet implemented by browsers, but BabelJs can transpile it.

function assertEmpty(obj) {
  if (Object.keys(obj).length > 0) {
    throw new Error("Unexpected parameters");
  }
}
    
class A {
  constructor({ a = "foo", ...rest } = {}) {
    assertEmpty(rest);
    console.log("new A " + a);
  }
}
    
class B extends A {
  constructor({ b = "bar", ...rest } = {}) {
    super(rest);
    console.log("new B " + b);
  }
}
    
new B({a:2}); // prints 'new A 2', 'new B bar'
new B({a:4, b:5, c:6}); // throws 'Unexpected parameters'

In the above snippet parent classes don't see the params consumed by the descendants. If you have problems with that you can do it either as @Bergi or @loganfsmyth suggested. For example:

class A {
  constructor(params = {}) {
    const { a = "foo" } = params;
    console.log("a=" + a);
  }
}

class B extends A {
  constructor(params = {}) {
    const { b = "bar" } = params;
    super(params);
    console.log("b=" + b);
  }
}

new B({a:2}); // prints a=2 b=bar
new B({b:5}); // prints a=foo b=5

Upvotes: 2

lebolnobel
lebolnobel

Reputation: 463

A quick-win is to use the arguments object. It is an array containing all parameters passed to a function.

More information on the MDN.

In practice, you can access to the first parameter of your function thanks to arguments[0].

class Child extends Parent {
    constructor({ parentOnlyArg = 'value',
                  visibleStyle = 'inline' } = {}) {
        super(arguments[0]);
        [...]
    }
}

Upvotes: 1

Related Questions