0

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)
  • Methods in classes in JavaScript can't be overloaded, which means there can't be multiple functions with the same name. To achieve something like this, you need to do something similar to the "Saransh Kataria" code you provided. I don't know what you mean by "so you can see using Saransh Kataria's Code, won't work.", as it will, you just need to change the `if` checkings for different lengths – Samathingamajig Nov 17 '20 at 22:57

1 Answers1

2

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")
        }
    }
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • @user13592230 - I added a code example. If you tell me what the data types are for the 5 possible parameters, I could probably code up a different version too by using data type detection. – jfriend00 Nov 17 '20 at 23:17
  • What about using static/class methods to initialise classes accordingly. e.g. `Book.empty()` and `Book.novel(500_pages)` both of which wrap the initialization of book instances with different parameters? – BenKoshy Nov 17 '20 at 23:22
  • 1
    @BKSpurgeon - Those would be referred to as "factory functions" (functions that take a set of arguments and construct a new object and return it to you). There are appropriate times to use factory functions. IMO, they don't make the code as readable as using `new` with an actual constructor, but if they seem better to you, you can do it that way. FYI, it is extremely common in Javascript to do dynamic detection of the arguments passed and adjust your code based on what was passed. IMO, it is one of the advantages of an untyped language. – jfriend00 Nov 17 '20 at 23:45
  • ok I will take your advice on the initailisation of javascript classes. – BenKoshy Nov 18 '20 at 01:53
  • @BKSpurgeon - Since it looks like you may be new here, if this answered your question, you can indicate that to the community by clicking the checkmark to the left of the answer. That will also earn you some reputation points for following the proper procedure here. – jfriend00 Nov 18 '20 at 02:25
  • I would if i could, but I cannot mark as "answered" because I am not the OP. – BenKoshy Nov 18 '20 at 02:30
  • @BKSpurgeon - Oh, I didn't realize you were a different contributor. OK, I guess we haven't heard anything back from the OP on this. – jfriend00 Nov 18 '20 at 02:31
  • Can Someone please make a library that makes this esayer? – Errorbot1122 THE SECOND Nov 18 '20 at 04:36
  • if you want to learn more about overloading you can go to https://www.youtube.com/watch?v=9w3zojKzuts&feature=emb_logo – Errorbot1122 THE SECOND Nov 18 '20 at 04:38
  • @Errorbot1122THESECOND - As I said in my comments, if you tell us what the types are of each of your 5 arguments, I could show you an easy way to do dynamic argument detection. It's not hard and would not require or probably even benefit from a library. – jfriend00 Nov 18 '20 at 04:42
  • @Errorbot1122THESECOND - If you really want function overloading built into the language, then you can use TypeScript which has C++ like function overloading like you were originally trying to do. See examples [here](https://www.tutorialsteacher.com/typescript/function-overloading). – jfriend00 Nov 18 '20 at 04:45
  • is typescript like Javascript? And if it is does it work on a webpage? – Errorbot1122 THE SECOND Nov 18 '20 at 18:50
  • @Errorbot1122THESECOND - Typescript is an extension of Javascript developed by Microsoft. To use it, you write code in TypeScript and then "compile" it to plain Javascript which can then be run in the browser. You will have to learn the "typing" system of TypeScript because (like in C/C++), it requires type definitions on all variables and function arguments. – jfriend00 Nov 18 '20 at 19:14
  • @Errorbot1122THESECOND - Here's a useful explanation of how TypeScript came into being: https://medium.com/jspoint/typescript-a-beginners-guide-6956fe8bcf9e and how it works. – jfriend00 Nov 18 '20 at 19:16
  • @jfriend00 - Also the Pram "Name" is a string, The Pram Type is String or a Number. The Pram Data is an Array. nd the Pram FileName is a String – Errorbot1122 THE SECOND Nov 18 '20 at 20:17
  • @Errorbot1122THESECOND - I added a version of the constructor that does dynamic argument detection. – jfriend00 Nov 18 '20 at 22:39