Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overload constructors in JavaScript ECMA6? [duplicate]

Objective

Implement a mechanism to allow constructor overload in JavaScript ECMA6

Why this is not a duplicate

The topic Why doesn't JavaScript ES6 support multi-constructor classes?, although similar is not the same as this one. The other topic merely focuses on a constructor overloading using the old ECMAScript versions, while this topic focuses on ECMA6. If you are looking for an updated answer, this is the place.

Background

I have a JavaScript class with a given constructor, and I want the user to be able to have different constructors when instantiating an object. An example of what I pretend could be the following:

const DEFAULT_WHEEL_NUMBER = 4;
const DEFAULT_COLOR = "black";    
const DEFAULT_NAME = "myCar";

class Car{

    constructor(numberWheels, aName, aColor){
        this.wheelsNum = numberWheels;
        this.name = aName;
        this.color = aColor;
    }

    constructor(aName){
        this(DEFUALT_WHEEL_NUMBER, aName, DEFAULT_COLOR);
    }

    constructor(){
        this(DEFUALT_WHEEL_NUMBER, DEFAULT_NAME, DEFAULT_COLOR);
    }
}

In this code, the user has three constructors he can use, each one taking a different amount of parameters. An usage example follows:

var car1 = new Car(3, "tricicle-car", "white");
var car2 = new Car("Opel"); //creates black car with 4 wheels called Opel
var car3 = new Car(); //creates a black car, with 4 wheels called myCar

Problem

This is a straightforward example if one is using Java or C#, because those languages have constructor overloads.

However, from the documentation on classes from MDN one can conclude that JavaScript does not.

Question

  1. Is there a way to implement a similar mechanism for JavaScript classes using ECMA6? If not, what is the best/closest alternative?
like image 818
Flame_Phoenix Avatar asked Jul 07 '16 08:07

Flame_Phoenix


People also ask

Can you overload constructors in JavaScript?

No you can't, JavaScript does not support overloading of any kind. What you can do is either pass an object which has already been populated with the values into your constructor and then grab the values from the object, but this which duplicates code.

Can you have 2 constructors in JavaScript?

There can be only one special method with the name constructor in a class. Having more than one occurrence of a constructor method in a class will throw a SyntaxError error.

Can you overload constructors?

Constructors can be overloaded in a similar way as function overloading. Overloaded constructors have the same name (name of the class) but the different number of arguments. Depending upon the number and type of arguments passed, the corresponding constructor is called.

Can TypeScript have multiple constructors?

In TypeScript, we cannot define multiple constructors like other programming languages because it does not support multiple constructors.


2 Answers

You're right (as far as I know) that this isn't a feature JavaScript classes support. My recommendation here, since you're already making use of ES6 features, would be to make use of default parameters instead:

class Car {
    constructor(numberWheels = 4, aName = "myCar", aColor = "black"){
        this.wheelsNum = numberWheels;
        this.name = aName;
        this.color = aColor;
    }
}

This obviously comes with the caveat that you can't have 'overloads' with different parameter orders like you do in your example (although in my opinion, that's a good thing - a consistent API is much nicer to work with).

meskobalazs's answer is also a good option, especially if you have a lot of options that you want your object to take in. Doing that through function params like this can get a bit messy!

like image 138
Joe Clay Avatar answered Oct 17 '22 11:10

Joe Clay


There is no in-built solution for this in JavaScript. An alternative solution can be using the arguments object (in some cases), or passing your own configuration options, similar to this:

const defaults = {
    numberWheels: 4,
    color: "black",   
    name: "myCar"
}

class Car {
    constructor(options) {
         this.wheelsNum = options.numberWheels || defaults.numberWheels;
         this.name = options.name || defaults.name;
         this.color = options.color || defaults.color;
    }
}

This is basically the old school solution, I use the same logic in ES3.

like image 36
meskobalazs Avatar answered Oct 17 '22 12:10

meskobalazs