Can you make multiple constructors in es6 and up?

Question

So basically I'm trying to make a class with multi constructors so that it is more user friendly. but when I run the code it outputs this:

SyntaxError: /FileSystem.js: Duplicate constructor in the same class (13:2)

I know that Creating multiple constructor in ES6 kind of answers this question but my code has different parameters for each constructor:

Varun Sukheja's code

    function Book() {
        //just creates an empty book.
    }
    
    
    function Book(title, length, author) {
        this.title = title;
        this.Length = length;
        this.author = author;
    }

My Code

    class File
        constructor(Name, Type, Data) {
            this.Name = Name
            this.Type = Type
            this.Data = Data
      }
        constructor(FileName, Data) {
        let FileNameSplit = FileName.split('.').pop(); 
        this.Type = FileNameSplit[FileNameSplit.length - 1];
        
        let NameSplit = FileNameSplit.pop()
        this.Name = FileName;
        
        this.Data = Data
      }
    }

As you can see, my code has 2 constructors (one with constructor(Name, Type, Data) { and the other with constructor(FileName, Data) { ). so you can see using Saransh Kataria's Code, won't work. .

Saransh Kataria's Code

    constructor(title, length, author) {
        if(!arguments.length) {
            // empty book
        }
        else {
            this.title = title;
            this.Length = length;
            this.author = author;
        }
   }

Extra Info

IDE: Codesandbox

Browser: Chrome

Full Code:

    class File {
      /**
       * 
       * @param {String} Name Name Of File
       * @param {(String|Number)} Type File Type / Exstention
       * @param {Array} Data 
       */
        constructor(Name, Type, Data) {
            this.Name = Name
            this.Type = Type
            this.Data = Data
      }
        constructor(FileName, Data) {
        let FileNameSplit = FileName.split('.').pop(); 
        this.Type = FileNameSplit[FileNameSplit.length - 1];
        
        let NameSplit = FileNameSplit.pop()
        this.Name = FileName;
        
        this.Data = Data
      }
    }

    let Blob1 = new Blob([""])

    console.log(Blob1)

Upvotes: 0

Views: 3079

Answers (1)

jfriend00
jfriend00

Reputation: 707198

Javascript does not support defining multiple constructors. It appears you're just trying to do function overloading.

In Javascript, you don't do it this way. Instead, you declare the version with the maximum number of parameters you expect and you dynamically test for what the OP passed and adjust your behavior based on what was or wasn't passed.

You can see a general description of function overloading in Javascript here:

How to overload functions in javascript?

If you have widely varying versions of the constructor, then you can change it to take exactly one object and then just assign the desired properties to the object before calling the function. Your code will then interrogate the object and see what was passed and adjust its behavior accordingly.

For example, to support both of these:

class File {
    constructor(Name, Type, Data) {
        this.Name = Name
        this.Type = Type
        this.Data = Data
  }
    constructor(FileName, Data) {
    let FileNameSplit = FileName.split('.').pop(); 
    this.Type = FileNameSplit[FileNameSplit.length - 1];
    
    let NameSplit = FileNameSplit.pop()
    this.Name = FileName;
    
    this.Data = Data
  }
}

there are several ways you could do something like this. The easiest is if the types of the desired parameters are distinct and we don't know exactly what types these are. Without knowing those types, I'd probably just pass in an object with named properties:

class File
    constructor(options) {
       if (options.Name && options.Type) {
           this.Name = options.Name
           this.Type = options.Type
           this.Data = options.Data
       } else if (options.FileName && options.Data) {
           let FileNameSplit = options.FileName.split('.').pop(); 
           this.Type = FileNameSplit[FileNameSplit.length - 1];
    
           let NameSplit = FileNameSplit.pop()
           this.Name = options.FileName;
    
           this.Data = options.Data
       } else {
           throw new Error("improper arguments to File constructor);
       }
    }
}

FYI, it's customary in Javascript that property names and argument names and regular variable names start with a lowercase letter (I left the code with the names you already had). Class names are typically capitalized.


Since you know that the Data argument is the only argument that is an array, you can dynamically detect which arguments are passed like this:

class File {
    // args can be in either of these forms:
    // (Name, Type, Data)
    // (FileName, Data)
    constructor(Name, Type, Data) {
        if (Array.isArray(Data)) {
            // args must be (Name, Type, Data)
            this.Name = Name
            this.Type = Type
            this.Data = Data
        } else if (Array.isArray(Type)) {
            // args must be (FileName, Data)
            const FileName = Name;
            this.Name = FileName;
            this.Data = Type;
            let FileNameSplit = FileName.split('.').pop(); 
            this.Type = FileNameSplit[FileNameSplit.length - 1];
        } else {
            throw new TypeError("unexpected or missing arguments to File constructor")
        }
    }
}

Upvotes: 2

Related Questions